Click here to Skip to main content
15,867,453 members
Articles / Web Development / ASP.NET

IIS vs. ASP.NET URL Rewriting

Rate me:
Please Sign up or sign in to vote.
4.77/5 (13 votes)
23 Nov 2009CPOL2 min read 67.7K   580   54   12
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.

Image 1

Solution code

C#
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:

C#
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:

C#
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:
  • Image 2

    If you use virtual hosting, it will look like this:

    Image 3

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)


Written By
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 Pin
cungo_bu16-Sep-13 18:01
cungo_bu16-Sep-13 18:01 
GeneralRe redirection to Login.aspx Pin
Ajay Kale New9-Sep-10 2:48
Ajay Kale New9-Sep-10 2:48 
GeneralRe: Re redirection to Login.aspx Pin
Alexandr Sergeevich Ilyin9-Sep-10 6:37
Alexandr Sergeevich Ilyin9-Sep-10 6:37 
GeneralRe: Re redirection to Login.aspx Pin
Ajay Kale New9-Sep-10 23:35
Ajay Kale New9-Sep-10 23:35 
GeneralWhere is " ~/Error404.axd" Pin
yaya rabiu david17-Aug-10 23:30
yaya rabiu david17-Aug-10 23:30 
GeneralRe: Where is " ~/Error404.axd" Pin
Alexandr Sergeevich Ilyin18-Aug-10 6:39
Alexandr Sergeevich Ilyin18-Aug-10 6:39 
GeneralThere IS elegant solution(at least in .NET 3.5 SP1) Pin
Selvin24-Nov-09 2:30
Selvin24-Nov-09 2:30 
GeneralRe: There IS elegant solution(at least in .NET 3.5 SP1) Pin
Alexandr Sergeevich Ilyin24-Nov-09 3:32
Alexandr Sergeevich Ilyin24-Nov-09 3:32 
GeneralRe: There IS elegant solution(at least in .NET 3.5 SP1) Pin
Ziv Nitzan2-Dec-09 19:57
Ziv Nitzan2-Dec-09 19:57 
GeneralRe: There IS elegant solution(at least in .NET 3.5 SP1) Pin
Alexandr Sergeevich Ilyin3-Dec-09 5:58
Alexandr Sergeevich Ilyin3-Dec-09 5:58 
Of course, it is. I am talking about virtual hosting and IIS 5.
GeneralRe: There IS elegant solution(at least in .NET 3.5 SP1) Pin
mkeeton7-Dec-09 0:27
mkeeton7-Dec-09 0:27 
GeneralRe: There IS elegant solution(at least in .NET 3.5 SP1) Pin
Alexandr Sergeevich Ilyin7-Dec-09 8:56
Alexandr Sergeevich Ilyin7-Dec-09 8:56 

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

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