The Problem
Over the past several years I've found myself running into the same problem over and over so I thought I'd blog the solution so at least I don't waste time figuring it out again. So, when do you need this? The answer for me is that I want to be able reference a web site without having to expose the underlying site structure. For example, on the home page of my business, I want people to be able to type http://73rdstreet.com/Home and be taken to http://www.73rdstreet.com/HomeSite/Home.aspx.
The Symptom
You may see errors that say something like:
Server Error in Application ... HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
MapRequestHandler StaticFile
And the screen may show something like this.
If this happens, read on.
Theory
The first thing to understand is that IIS by default will pass to the asp.net process only the requests that have a certain file extension. That is, aspx,ashx,etc. Basically, only file extensions that have a handler defined for them to be processed by. Other URL's that don't meet the criteria are not passed to IIS. This includes no file extension at all. There is a good reason for this. One, it makes processing of things like images (jpg's, gif's, etc.) faster because they do not every have to be processed through the asp.net worker process. Secondly, it lowers the exposure of the asp.net worker process so that it is less likely to be compromised.
So, the first thing that has to be done is to tell IIS to pass all requests through using something called Wild Card Mapping. Then, once this is done, the request comes through to the asp.net worker process regardless of what it is. As we know, the place that we would have to process this is an HttpModule. The reason is that since it's not a page yet, we have no idea what to do with it. Basically modules let you tap into the request at different stages. To do the rewrite from ../Home to ../HomeSite/Home.aspx we want to tap into the Application_BeginRequest event. The Context.RewritePath method is called at that point to force a new path based on what we want (hopefully not hard coded).
After the ReWritePath is set, the page is processed as if is going to the correct page.
How To Set Wild Card Mapping in IIS6
To Set Wild Care Mapping in IIS6 you need to do the following.
Run inetmgr and navigate to the Properties page of the website you want to set.
Then, from the properties page, click the Configuration button as shown below.
Then, press the insert button on the configuration screen and see the following screen and then click on the insert button.
Now, insert your asp.net isapi dll. On my system, the file is here: C:WINDOWSMicrosoft.NETFrameworkv2.0.50727aspnet_isapi.dll. Make sure to uncheck the box "Verify that file exists".
That's it! Now, all requests will be processed through you asp.net pipeline so you will be able to intercept anything on the URL you want. Be careful though, you may get more than you ask for!
How To Set Wildcard Mapping in IIS7
In IIS7 things are a little different. First thing you need to do is unlock the config section "handlers". You do this by bring up a DOS prompt and entering the command:
C:WindowsSystem32inetsrv>appcmd.exe unlock config /section:system.webserver/handlers
Then, you can set your wildcard handler in your web.config file as follows.
Now, the default handlers will be executed in your web.config file, and of course, all the defaults for that are in the chain of files that inherits from. For more details on that, see this FAQ: Configuration Files FAQs (web.config, machine.config...).
You may need to add the wildcard mapper handler to your web.config. To do this, you would put the following in your web.config
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <handlers> <add name="WildCard" path="*" verb="*" type="sampletype" resourceType="Unspecified" /> </handlers> </system.webServer> </configuration>
Now, you should be set. See the next section for a good method for actually doing the remapping, which is why we went down this path in the first place.
Implementing a URL ReWriter for Mapping ../Home to ../HomeSite/Home.aspx
So, as discussed in the theory section above, you could write your own code to map what you want to where you want it. You could put in your global.asax some code for the Application_BeginRequest and make a big case statement for everything you want to do. Well, as we know, that would give your code a bad smell and we don't want that because soon, you will find yourself using cut and paste and other problematic crutches.
So, to avoid all that, and do what Scott Guthrie suggests, use the open source package UrlRewriter.NET. It's light-weight and configurable through a small section in your web.config. Before putting in the what to do, here are the steps to make UrlRewriter work in a very simple way (the way I use it on my company home page.
In your <System.web> of your web.config place a definition for a new config section where you will put your rewrites
<configuration>
<configSections>
<section name="rewriter" requirePermission="false"
type="Intelligencia.UrlRewriter.Configuration.RewriterConfigurationSectionHandler, Intelligencia.UrlRewriter"/>
Then, put the module that actually does the work of the rewrite as described in the theory section above
<system.web>
<httpModules>
<add name="UrlRewriter"
type="Intelligencia.UrlRewriter.RewriterHttpModule, Intelligencia.UrlRewriter" />
</httpModules>
..
Then, further down in your web.config put
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules>
<add name="UrlRewriter"
type="Intelligencia.U
<rewriter>
<rewrite url="~/Home" to="~/pages/Home.aspx"/>
</rewriter>
That's it! You are done. Hope this helps, or at least helps me the next time I'm searching for the same problem (for the 4th time at least).
References:
- http://devtalk.dk/2007/03/19/Wildcard+Mapping+And+URL+Rewriting+On+IIS7.aspx
- http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx
- http://urlrewriter.net/
- http://forums.asp.net/t/1240344.aspx
- http://professionalaspnet.com/archive/2007/07/27/Configure-IIS-for-Wildcard-Extensions-in-ASP.NET.aspx
- http://professionalaspnet.com/archive/2007/07/27/Create-an-HttpModule-to-Process-Wildcard-Extension-Mapping-in-ASP.NET.aspx