Everyone likes a friendly URL

As part of our BEA World strategy for this year, we’re revamping our corporate web site, http://www.bdg-online.com. You should expect an unveiling in the upcoming weeks.

While there will be some revised and some additional content, this is primarily an infrastructure upgrade, including moving to more powerful virtual hosts and upgrading the backend from ASP to ASP.NET (yes, I know, it’s about time).

One of things that really bugs me about ASP and ASP.NET is the failure to include built-in support for friendly URLs. By friendly I mean something that doesn’t end in .asp, .htm, .aspx or some other extension and naturally also doesn’t have a querystring (?foo=bar&boo=moo . . . etc.). For example, http://www.bdg-online.com/customers is a lot more friendly than http://www.bdg-online.com/customers.asp and definitely more friendly than something like http://www.bdg-online.com/content.aspx?p=/customers.

Java provides a nice facility for this in the form of servlet mappings. Since a lot of people are using MVC these days, you are probably going to set up servlet mappings anyway. Here’s an example from a sample web.xml file:

<servlet>
 <servlet-name>customers</servlet-name>
 <servlet-class>com.bdg-online.www.Customers</servlet-class>
</servlet>

<servlet-mapping>
 <servlet-name>customers</servlet-name>
 <url-pattern>/customers/*</url-pattern>
</servlet-mapping>

But what about ASP or ASP.NET? No one cares about ASP any more, so I didn’t bother to research that. But for .NET, I came up with a simple and elegant solution to the friendly URL problem. All you need to do is add the following code (or something like it) to your Global.asax.cs file:

protected void Application_BeginRequest(Object sender, EventArgs e)
{
 if (!Request.RawUrl.EndsWith("htm") &&
     !Request.RawUrl.EndsWith("css") &&
     !Request.RawUrl.EndsWith("ico") &&
     !Request.RawUrl.EndsWith("jpg") &&
     !Request.RawUrl.EndsWith("js") &&
     !Request.RawUrl.EndsWith("gif"))
 {
   if ("".Equals(Request.RawUrl) || "/".Equals(Request.RawUrl))
   {
     Context.Server.Transfer("default.aspx");
   }
   else
   {
     Context.Server.Transfer(Request.RawUrl + ".aspx");
   }
 }
}

You’ll note that I forward requests to the corresponding aspx page, as long as the request isn’t for static content (images, css, etc.).

Of course you also need to do two things:

  1. Configure an .aspx page for every friendly URL you want resolved
  2. Add a wildcard mapping in IIS for * (files without extensions) to the asp.net ISAPI filter

The process for #2 is a little involved. It’s also different for IIS 5 (XP) and IIS 6 (2003). I don’t feel like posting screen shots right now, but if anyone wants to give this a trial run and can’t figure out how to do #2, just e-mail me and I’ll walk you through it.

I just came up with this a couple of hours ago and I haven’t put it through much testing, so YMMV.

Leave a Reply