In my article URL Rewriting in ASP.NET I showed how to use URL rewriting to allow for rewriting from a “pseudo” URL, like /Products/Meat.aspx, to a real URL, like /ListProducts.aspx?CatID=1. (By “pseudo” I mean that on the Web server the file /Products/Meat.aspx doesn't exist. Rather, when the request comes in for that file and is handed to the ASP.NET engine, the ASP.NET engine examines user-defined rewrite rules to determine to (behind the scenes) rewrite the incoming requested URL to /ListProducts.aspx?CatID=1, which does exist and displays the meat-related products. The benefit to the user - they get to see/use a memorable URL, one devoid of messy querystring parameters.) Additionally, if a user visited the directory /Products/ (or /Products/default.aspx), the user would see a list of the product categories.
One of the subtleties of this approach is that while the file /Products/Meat.aspx did not really need to exist, the directory /Products/ needed to exist in order to serve requests to /Products/ (but not to /Products/default.aspx). Why? Because if a user entered into their browser www.yoursite.com/Products/, IIS would handle the request and not hand it off to the ASP.NET engine. IIS would say, “Hey that directory doesn't exist,” and return a 404 HTTP response. (The request to /Products/default.aspx would work because IIS would hand off the request to the ASP.NET engine since the request was clearly for an ASP.NET resource - default.aspx.) Therefore, to implement this end user-friendly URL scheme, you would need to create a /Products/ directory and a dummy default.aspx. That way, when a request came in to /Products/, IIS would say, “Yes, that directory exists. And yes, it has a default.aspx file, so let me hand off the request to the ASP.NET engine.”
In my article I discussed a workaround to needing to create these “dummy” directories was to map all incoming requests from IIS to the ASP.NET engine. This way, even a request for /Products/ will get routed to the ASP.NET engine without IIS checking to see if /Products/ exists and if there is a default.aspx file in that directory. Unfortunately, completely implementing this solution is not just as simple as flipping the switch on IIS to pass all incoming requests to the ASP.NET engine. In fact, there has been a good discussion on my previous blog entry announcing the URL rewriting article. Some of the problems noted is that the default page for a directory won't load. That is, a request to /Products/ won't bring up /Products/default.aspx. Also, requests to non-ASP.NET files - such as images, CSS classes, external JavaScript files, etc. - don't work.
The problem arises because all requests are being mapped to the ASP.NET engine. Requests to image files. Requests to CSS files. Requests to just the directory path /Products/ (not /Products/default.aspx). So, if you want to use this approach of mapping all files to the ASP.NET engine, you're going to have to make the ASP.NET engine a bit smarter (and tell it how to handle all of the potential file requests that might come in). This is most easily done by creating HTTP handlers for different types of content that might need to be served. For example, you could create an HTTP handler that would know how to serve content like images, CSS files, external JavaScript files, etc. Your “catch-all” handler would need to know that if a request came in that looked like /Products/, that it would have to append default.aspx to the request and retry.
To get a good understanding of how to accomplish this, check out the .Text source code. In the Configs/Multiple1_Web.config file you can see an example of mapping image/CSS files to a static HTTP handler:
<HttpHandler pattern = "(\.gif|\.js|\.jpg|\.zip|\.jpeg|\.jpe|\.css)$" type = "Dottext.Common.UrlManager.BlogStaticFileHandler, Dottext.Common" handlerType = "Direct" />
In Code/Dottext.Common/UrlManager/BlogStaticFileHandler.cs you can see how static content (images/CSS files/ZIP files) are served. In Code/Dottext.Common/UrlManager/PageHandlerFactory.cs you can see how directory requests - like /Products/ - are handled. There's even examples of URL rewriting at work in Code/Dottext.Common/UrlManager/UrlReWriteHandlerFactory.cs class.
The point is, if you map all requests to the ASP.NET engine, then you have to essentially replicate the work IIS does through custom HTTP handlers. Hope this helps some folks struggling through mapping all requests in IIS to the ASP.NET engine!