Introduction
Richard Birkby has written a perfect article on URL Rewriting with ASP.NET. This article is just a patch to it for how to handle directory access.
Problems
Using Richard's framework (it's really cool!), we can hide "http://www.apache.org/BookDetails.pl?id=5" and use a well formed URL like: "http://www.apache.org/Book/5.html". But it can't handle URLs like these:
- http://www.apache.org/Book/Java/
- http://www.apache.org/Book/C#/
Because, ASP.NET will try to resolve this directory and find "default.aspx" in it. Of course, it will return a 404 Not Found Error.
The Simple Way: Step 1
First, we should update the web.config file as follows:
<httpHandlers>
<add verb="*" path="Default.aspx" type="URLRewriteHandler"/>
<add verb="*" path="*/" type="URLRewriteHandler"/>
</httpHandlers>
We add a handler which maps to Default.aspx; it will work when we access the "/" of a virtual path. And another handler is mapped to "*/"; it will work when we access a directory, e.g., "/some/path/". Now, URLRewriteHandler
can handle directory access which ends with a "/".
The Simple Way: Step 2
Want to see what happens if someone types in "http://www.apache.org/Book/Java"? We still will get a 404 Not Found Error. It means that we should handle URLs which have no extension, but we can't write this mapping in web.config directly, because ASP.NET won't recognize it.
How should we think about "http://www.apache.org/Book/Java"? Is it a wrong URL? Yes! All we need to do is correct this mistake using the correct URL (which has a "/" at the end of the line). The idea is to write an HTTP module to handle the wrong URL and force the client to redirect to the correct path.
public class URLCheckingModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Context_OnBeginRequest);
}
private void Context_OnBeginRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
HttpRequest request = context.Request;
string file = request.FilePath;
string ext = Path.GetExtension(file);
if (string.IsNullOrEmpty (ext) && ! file.EndsWith ("/"))
{
string q = request.QueryString.ToString ();
string path = request.FilePath + "/" +
(string.IsNullOrEmpty(q) ? "" : q) ;
context.Response.Redirect(path);
}
}
public void Dispose()
{
}
}
Then register it in Web.config:
<httpModules>
<add name="URLChecking" type="URLCheckingModule"/>
</httpModules>