posts - 234, comments - 480, trackbacks - 56

My Links

News




I am born in Bangladesh and currently live in Melbourne, Australia. I am a co-founder and core developer of Pageflakes www.pageflakes.com and CEO at Simplexhub, a highly experienced software development company based in Melbourne Australia and Dhaka, Bangladesh.

I also created SmartCodeGenerator

Some of my articles
Flexible and Plugin based .Net Application..
Mass Emailing Functionality with C#, .NET 2.0, and Microsoft® SQL Server 2005 Service Broker'
Write your own Code Generator or Template Engine in .NET
Smart Code Generator .NET: Usage Overview
Smart Code Generator .NET: Architectural Overview
Smart Code Generator .NET: using with NAnt and Cassini

Archives

Free Programming Language Training

Tuesday, May 19, 2009

ASP.NET MVC Tips: 301 Redirect non-www versions of URL to www.

Search Engine Optimization guides, recommends to have one version of a URL of the same content. Search engines may pickup www and non-www versions of URL as 2 separate URLs, i.e. http://xyz.com/page1 may be considered different to http://www.xyz.com/page1. It is a good idea to pick on of these URLs as preferred and use 301 redirects to send traffic from the other URLS to the preferred URL. Today we will pickup www version of URL as our preferred URL and look at how we can redirect the non-www version of the URL to our preferred URL structure using ASP.NET MVC.


Workflow 

We can achieve the above by writing a custom handler that extends from the MvcHandler. We are basically interested in the ProcessRequest method where we can get hold of the non-www version of the URL to replace it to the www. version of URL.

    public class The301GlobalHandler : MvcHandler
    {
        public The301GlobalHandler(RequestContext requestContext) : base(requestContext) { }

        protected override void ProcessRequest(HttpContextBase httpContext)
        {
            //We do not want this handler to process local requests
            if (httpContext.Request.IsLocal)
                base.ProcessRequest(httpContext);
            else
                ProcessExternalRequest(httpContext);
        }

        private void ProcessExternalRequest(HttpContextBase httpContext)
        {
            bool urlChanged = false;
            string url = RequestContext.HttpContext.Request.Url.AbsoluteUri;
            //Check for non-www version URL
            if (!RequestContext.HttpContext.Request.Url.AbsoluteUri.Contains("www"))
            {
                urlChanged = true;
                //change to www. version URL
                url = url.Replace("http://", "http://www.");                    
            }
            ProcessExternalRequest(url, urlChanged, httpContext);
        }

        private void ProcessExternalRequest(string url, bool urlChanged, HttpContextBase httpContext)
        {
            if (urlChanged)
            {
                //mark as 301
                httpContext.Response.Status = "301 Moved Permanently";
                httpContext.Response.StatusCode = 301;
                httpContext.Response.AppendHeader("Location", url);
            }
            else
                base.ProcessRequest(httpContext);
        }
    }

The above code is self explanatory, we are checking if the Request is local or external, we are only interested on external URLs. Next we check, whether the RequestContext.HttpCOntext.Request.Url.AbsoluteUri contains a "www" or not. If it do not contain a "www" we go and inject a "www" to the URL to convert the non-www version of URL to a www. version URL. Then we mark the previous response to a 301, which indicates that the previous URL has been permanently removed and all future requests should be directed to the given new URL. 

We have developed our core handler above, however we need a wrapper IRouteHandler class to get the above The301GlobalHandler to work within the MVC Framework. This wrapper class is responsible to return an instance of the The301GlobalHandler.

    public class Route301GlobalHandler : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new The301GlobalHandler(requestContext);
        }
    }


We have got our Route301GlobalHandler ready, now we need all of our requests to go via this handler instead of the default. One easy way to do this, is to iterate through the route collection and  assign them to this Route301GlobalHandler during the Application_Start().

    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
        Route301Global.ReAssignHandler(RouteTable.Routes);
    }
    public static class Route301Global
    {
        public static void ReAssignHandler(RouteCollection routes)
        {
            using (routes.GetReadLock())
            {
                AssignRoute301GlobalHandler(routes);
            }
        }

        private static void AssignRoute301GlobalHandler(IEnumerable<RouteBase> routes)
        {
            foreach (var routeBase in routes)
            {
                AssignRoute301GlobalHandler(routeBase);
            }
        }

        private static void AssignRoute301GlobalHandler(RouteBase routeBase)
        {
            var route = routeBase as Route;
            if (route == null) return;
            if (route.RouteHandler.GetType() != typeof(Route301Handler))
                route.RouteHandler = new Route301GlobalHandler();
        }
    }

Note, if you have other custom RouteHandler in your application, you will need to tweak this code, I am assuming all routes that will be mapped in the RegisterRoutes(RouteCollection routes) method uses the MvcHandler.

Conclusion

We have identified keeping one set of URL is important for SEO. Then we have looked at how we can 301 redirect non-www version of URL to www. version URL in ASP.NET MVC. Hope this saves you some time and thank you for being with me so far.

posted @ Tuesday, May 19, 2009 1:02 AM | Feedback (2) |

Powered by: