Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

IIS vs. ASP.NET URL Rewriting

0.00/5 (No votes)
23 Nov 2009 1  
A solution to use ASP.NET URL rewriting with virtual hosting and old IIS versions.

Introduction

It is important for web sites to have user friendly URLs, it helps search engine optimization and improves user-experience. In ASP.NET, nice URLs can be achieved by using URL rewriting, but deployment of such applications may be annoying. The problem is that when IIS receives a request like mydomain.com/products/3, it does not use ASP.NET to process it. Instead, IIS tries to find the file products/3 in the website folder and returns error 404 to the client. Unfortunately, there is no elegant solution, but an ugly one does exist.

Solution concept

If you have full control over the server where your application is hosted, you are lucky - it is enough to make all requests processed by the same DLL which processes .aspx files. Unfortunately, it is not always possible. For example, when virtual hosting or IIS 5 is used. So there is plan B. We configure the website to use error404.axd as the error 404 page URL. When a request like mydomain.com/products/3 is received, IIS will use ASP.NET to open error404.axd?http://mydomain.com/products/3. This allows us to use URL rewriting and fix up the URL.

Solution code

public class Error404RewritingModule : IHttpModule
{
  private static readonly FieldInfo HttpMethodFieldInfo;
  private static readonly FieldInfo HttpVerbFieldInfo;
 
  public void Init(HttpApplication context)
  {
    context.BeginRequest += OnBeginRequest;
  }
 
  static void OnBeginRequest(object sender, EventArgs e)
  {
    HttpContext httpContext = HttpContext.Current;
    HttpRequest httpRequest = httpContext.Request;
    //
    string targetPath = httpRequest.AppRelativeCurrentExecutionFilePath;
    if (!targetPath.StartsWith("~/Error404.axd", 
               StringComparison.InvariantCultureIgnoreCase))
      return;
 
    Uri requestedUrl = httpRequest.Url;
    var currentApplicationUrl = new Uri(requestedUrl, httpRequest.ApplicationPath);
    //
    // Extract initially requested url
    string initiallyRequestedUrl = ExtractInitiallyRequestedUrl(requestedUrl.Query);
    string initiallyRequestedQuery = ExtractInitiallyRequestedQuery(initiallyRequestedUrl);
    string initiallyRequestedVirtualPath = GetInitiallyRequestedVirtualPath(
      currentApplicationUrl, initiallyRequestedUrl);

    if (String.IsNullOrEmpty(initiallyRequestedQuery)) 
      httpContext.RewritePath("~/Hack", "/", "a=b", true);
         
    if (!String.Equals(httpRequest.HttpMethod, "POST", 
                 StringComparison.InvariantCultureIgnoreCase))
       if (httpRequest["__VIEWSTATE"] != null || 
           httpRequest["__EVENTTARGET"] != null) {
        HttpMethodFieldInfo.SetValue(httpRequest, "POST");
        HttpVerbFieldInfo.SetValue(httpRequest, 5); // 5 = POST
      }

    httpContext.RewritePath(initiallyRequestedVirtualPath, null, "", true);    
  }
...
}

There are two interesting places; the first is the following:

if (String.IsNullOrEmpty(initiallyRequestedQuery)) 
   httpContext.RewritePath("~/Hack", "/", "a=b", true);

It would take a deep diving into ASP.NET internals to explain this, but the reason is the following. If the query string is empty, then HttpRequest.Current.Url is not changed by rewriting sometimes. The second place of interest is:

if (!String.Equals(httpRequest.HttpMethod, "POST", 
            StringComparison.InvariantCultureIgnoreCase))
  if (httpRequest["__VIEWSTATE"] != null || httpRequest["__EVENTTARGET"] != null) {
    HttpMethodFieldInfo.SetValue(httpRequest, "POST");
    HttpVerbFieldInfo.SetValue(httpRequest, 5); // 5 = POST
  }

It is required because IIS 6.0 passes a GET request to Error404.axd, even if the client sends POST. So this code hacks HttpRequest to make it POST again.

Usage

  • Place Xtensive.Web.Deployment.dll in the bin folder of your application and add the following to the httpModules configuration section:
  • <httpModules>
       <add name="LiveUI.Error404-Handler" 
           type="Xtensive.Web.Error404RewritingModule, Xtensive.Web">
    </httpModules>
  • Configure the website to use error404.axd as the error 404 (error 405) page URL. If you use IIS, it will look like this:
  • If you use virtual hosting, it will look like this:

Conclusion

You might not like the solution presented, neither do I, but it is better than nothing. Initially, I developed this module to help LiveUI users to deploy their applications, so it was tested on LiveUI demos. But there should be no problems in using it with other frameworks such as ASP.NET MVC or UrlRewriting.NET.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here