ActionFilter to render a different view for web crawlers

There are SEO problems while using frameworks like KnockoutJS or AngularJS or ReactJS. The page loads, then javascript loads. JavaScript renders the HTML elements. Web crawlers of today do not execute the JavaScript. So, the page content is often missing or incorrect. Hence, the SEO suffers.

Update (Sep 2017): Search engines, especially Google, runs the JavaScript. SEO has improved for JavaScript frameworks.

MVC Framework Overview

If you are new to ASP.NET MVC, the framework performs the following steps to render a response:

  1. From the route, find the controller class and action method.
  2. Call any ActionFilter before invoking the action.
  3. Invoke the action method to get an ActionResult.
  4. Call any ActionFilter after invoking the action.
  5. Call any ResultFilter before generating a response.
  6. Invoke ExecuteResult method of ActionResult to generate a response.
  7. Call any ResultFilter after generating the response.

ActionFilter for Crawlers

To overcome the SEO problem, we render a different view for Web crawlers. This is accomplished using an ActionFilter. We provide an action filter before invoking the action (Step 4).

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    string id = (string)filterContext.ActionParameters["id"];
    var post = PostComp.GetPost(id);
    filterContext.ActionParameters["post"] = post;
    var controller = filterContext.Controller as BaseController;
    if (controller.Request.Browser.Crawler)
    {
        // If you are a crawler, I got you a special page!
        var viewName = "Crawler" + filterContext.ActionDescriptor.ActionName;
        filterContext.Result = controller.GetViewResult(viewName, post);
    }
    else
    {
        // If you are not a crawler, go to the cool page that we got.
        base.OnActionExecuting(filterContext);
    }
}

We detect if the request is made by a crawler using Request.Browser.Crawler property. Default view name is the action name. The new view name is prefixed with Crawler. Use the GetViewResult method of the controller to get a ViewResult (subclass of ActionResult). Pass the model to the method. So that the ViewResult has the associated model.

We attach the ViewResult to the filter context. Since a result is generated in the action filter, the subsequent action method is not called. Instead, we move directly to generate a response from the ViewResult. The MVC framework takes the ViewResult and renders a view as response by calling the ExecuteResult method.

We serve a different view for the crawler by using an ActionFilter. Though not the most elegant technique, it works. And we have a lot of control over our crawler view.

Related Posts

Leave a Reply

Your email address will not be published.