Click here to Skip to main content
Click here to Skip to main content

IIS vs. ASP.NET URL Rewriting

, 23 Nov 2009
Rate this:
Please Sign up or sign in to vote.
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Alexandr Sergeevich Ilyin
Software Developer Xtensive
Russian Federation Russian Federation
I've been working at Xtensive company for 3 years.
My current project is LiveUI web framework which should make everybody happy. If I can be of any help to you feel free to contact me alexandr.ilyin at gmail.com.
 
By the way, I have a blog.


Comments and Discussions

 
QuestionParameters in POST request Pinmembercungo_bu16-Sep-13 18:01 
GeneralRe redirection to Login.aspx PinmemberAjay Kale New9-Sep-10 2:48 
GeneralRe: Re redirection to Login.aspx PinmemberAlexandr Sergeevich Ilyin9-Sep-10 6:37 
GeneralRe: Re redirection to Login.aspx PinmemberAjay Kale New9-Sep-10 23:35 
GeneralWhere is " ~/Error404.axd" Pinmemberyaya rabiu david17-Aug-10 23:30 
GeneralRe: Where is " ~/Error404.axd" PinmemberAlexandr Sergeevich Ilyin18-Aug-10 6:39 
GeneralThere IS elegant solution(at least in .NET 3.5 SP1) PinmemberSelvin24-Nov-09 2:30 
GeneralRe: There IS elegant solution(at least in .NET 3.5 SP1) PinmemberAlexandr Sergeevich Ilyin24-Nov-09 3:32 
GeneralRe: There IS elegant solution(at least in .NET 3.5 SP1) Pinmemberzivni2-Dec-09 19:57 
GeneralRe: There IS elegant solution(at least in .NET 3.5 SP1) PinmemberAlexandr Sergeevich Ilyin3-Dec-09 5:58 
GeneralRe: There IS elegant solution(at least in .NET 3.5 SP1) Pinmembermkeeton7-Dec-09 0:27 
GeneralRe: There IS elegant solution(at least in .NET 3.5 SP1) PinmemberAlexandr Sergeevich Ilyin7-Dec-09 8:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140821.2 | Last Updated 23 Nov 2009
Article Copyright 2009 by Alexandr Sergeevich Ilyin
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid