-
-
Setting up ASP.Net MVC 2 on IIS6 with IISRewrite
June 2, 2010 -
This will also work in ASP.net MVC, as in the first one.
It’s a somewhat well known fact, (by somewhat I mean for amongst web devs, my mum wouldn’t understand any of that), that IIS6 is the IE6 of Servers, its slow, dim-witted, annoying, crap and here to stay.
So to make life a little more bearable and to save the rest of the web-society from a life of .net 2 webform’s, bloated view states and ugly urls here’s a quick “how to”.
This How To Covers:
-
Setting up your Visual Studio Project for ASP .NET MVC2
-
Creating the project
-
Editing the global.asax file
-
Changes Dissected
-
-
Setting up IIS6 for ASP.Net MVC2
-
Setting up Rewriting (.htaccess file)
-
Why don’t we use Wild Cards
-
Setting up your Visual Studio Project for ASP .NET MVC2
Creating the project
This code should fit quite nicely into your code wether your using IOC ala Ninject or already have a load of stuff in your global.asax.cs file.
Anyhoo onwards; go and create a new project; select new MVC2 Web Application; I like to keep all of the junk in, it lets me exercise the delete button once I know the servers behaving.

That’s pretty much that tiny step done with.Editing the global.asax file
Pop open your global.asax.cs file in Visual Studio and look for ‘public class MvcApplication(){‘ shouldn’t be too hard to see there should be very little in there.

At this point you can see (as above) right at the start of ‘public class MvcApplication {‘ our magic will happen… copy and paste the following code there.#region SEO URL Management #region 301Redirect Method /// <summary> /// Redirect old URL to new URL via 301 Header Redirect (SEO Friendly Permanent Redirect) /// </summary> /// <param name="url"></param> private void PermanentRedirect(string url) { Response.Clear(); Response.Status = "301 Moved Permanently"; Response.AddHeader("Location", url); Response.End(); } #endregion #region MVC Request Cleaner /// <summary> /// Cleans up passed urls to reduce the number of alternate routes to the same content /// Strips postfix slash; etc, as in the comments. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void Application_BeginRequest(Object sender, EventArgs e) { #region Rewriting IIS6 Fix 27112009 var app = sender as HttpApplication; if (app != null) if (app.Request.AppRelativeCurrentExecutionFilePath == "~/rewritten.aspx") app.Context.RewritePath( app.Request.Url.PathAndQuery.Replace("/rewritten.aspx", "") ); #endregion Rewriting IIS6 Fix // Get the requested URL so we can do some validation on it. // We exclude the query string, and add that later, so it's not included // in the validation string url = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath); // If we're not a request for the root, and end with a slash, strip it off if (HttpContext.Current.Request.Url.AbsolutePath != "/" && HttpContext.Current.Request.Url.AbsolutePath.EndsWith("/")) PermanentRedirect(url.Substring(0, url.Length - 1) + HttpContext.Current.Request.Url.Query); // If we end with /1 we're a page 1, and don't need (shouldn't have) the page number if (HttpContext.Current.Request.Url.AbsolutePath.EndsWith("/1")) PermanentRedirect(url.Substring(0, url.Length - 2) + HttpContext.Current.Request.Url.Query); // If we have double-slashes, strip them out else if (HttpContext.Current.Request.Url.AbsolutePath.Contains("//")) PermanentRedirect(url.Replace("//", "/") + HttpContext.Current.Request.Url.Query); // If we've got uppercase characters, fix else if (Regex.IsMatch(url, @"[A-Z]")) PermanentRedirect(url.ToLower() + HttpContext.Current.Request.Url.Query); } #endregion #endregion SEO URL Management
I’ve left in the regions so this can be nicely shrunken down rather then making your global asax file look like a garbage dump.
Compiling now should run just fine and you should be able to test out the edits by attempting to load /Home/About/ (should go to lowercase and strip off the last slash)
Dissecting the Code
Firstly we have the ‘PermanentRedirect’ method which I wont go into much detail explaining as the codes not changed much since classic-asp, but basically it sets an SEO friendly ‘HTTP/1.1 301 Moved Permanently Location: http://etc’ on the URL to the rewritten URL. This methods simply here for to facilitate the rest of the code.
Next we have Application_BeginRequest where we pick up the HttpContext request and make our alterations.
Firstly we have our IIS6 fix; which I’ll delve into the “why” in a moment; but simply this takes the request, grabs the path and query and strips out the ‘/rewritten.aspx’ bit. Not necessary in IIS7/8 but it sure as shit beats App-WildCard in IIS6.
The codes pretty well commented but lets expand on it a bit.string url = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath);
We capture the URL in its component parts, avoiding the Query String as we really don’t want to transform anything being carried in there.
string url = (Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority + HttpContext.Current.Request.Url.AbsolutePath); Request.Url.Scheme // this bit will return http or https, basically the bit before :// HttpContext.Current.Request.Url.Authority // this will return the DNS name or IP address HttpContext.Current.Request.Url.AbsolutePath // returns the rest of the path
Or for extra imagery…
The first if statement checks for slashes, if its the root we leave it alone, if its not the route we make sure the URL doesn’t end in a slash. This may not seem like a major thing but if you have http://www.mysite.com/stuffisell/ and somewhere else you accidently link to http://www.mysite.com/stuffisell, although it may not throw an error or cause you any “major” issues, google will count that as 2 unique URL’s serving identical content which is crap for SEO.
Next we check for page 1, this usually occurs in results pages but the scenario is the same as above and as your default route for a results page would be the first page its unnecessary.
Almost at the end; we then check that were not accidently passing double slashes, this is usually a user error but when you consider that anyone could link to your site its good to cover your bases.
And last but not least, converting to lowercase, a quick regex check for uppercase characters and if they exist convert the url to lowercase. I’ve not sure if this would benefit from the compiled regex flag as its a bit of a rabbit hole and so far I’ve not seen any reason to use it. If I get around to it I’ll do a quick 10K run test and see if theres a big improvement vs offset. Probably wont be as this is a REALLY basic regex test
That’s pretty much all of that bit.
Setting up Rewriting (.htaccess file)
I’ll cut to the chase heres the .htaccess file for your site; your rules may vary
slightly if your using IIRF instead of ISAPIRewrite. I prefer IIRF in general, but work seems to prefer ISAPIRewrite, lets not assume they’re right though as they just took the advice of a consultant.# Helicon ISAPI_Rewrite configuration file # Version 3.1.0.64 RewriteEngine on # Add any standard 301 Redirections between here # Dont Add any standard 301 Redirections after here # MVC + Standard Rules RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # Add extensions to this rule to avoid them being processed by ASP.NET RewriteRule (.*)\.(css|gif|png|jpeg|jpg|js|zip) $1.$2 [I,L] # Prefixes URLs with "rewritten.aspx/", so that ASP.NET handles them RewriteRule ^(.*) /rewritten.aspx/$1 [I]Now you can see where the rewritten.aspx comes in, using a file-typed filename causes IIS to pass the file through the asp.net handler, without having to resort to the wild card method.
Why don’t we use WildCards or a .mvc extension
In short overhead and vanity; wild carding will cause EVERYTHING to go through ASP.Net (aspnet_isapi.dll) including your static file requests; and adding an extension to the end of the file a) exposes the technology pointlessly, b) makes ugly urls and c) takes away from why your doing this in the first place.
References
This systems a bit of an amalgamation of fixes and optimizations but the system to get around the asp wildcard came from Mr. Sanderson http://bit.ly/9a0sjS. God knows where the other bits came from.
Project File
Download the MVC2 Solution – IIS6SEOHowTo.zip
-
-

