In an ideal world, we'd design our Web applications perfectly the first time. Pages would be created in the proper folder and stay there. For that matter, end users would never care about the URLs of the pages in our Web applications, so we could put pages anywhere we wanted without worrying about it.
In the real world, things aren't quite that simple. You may decide after you've released an application that you really want to reorganize the folder structure. Alternatively, users might want to see URLs like http://www.example.com/widget.aspx in place of http://www.example.com/Products/W/widget.aspx. Making such changes after you've put together an ASP.NET application is at best tedious and at worst requires costly rewriting of code.
Fortunately, ASP.NET 2.0 introduces a new tool to make such changes simple: URL mapping. In this article, I'll show you how to implement URL mapping in an ASP.NET 2.0 site. I'll also discuss the limitations of this technique and show you some alternatives to get around those limitations.
URL Mapping in Action
Let's take that Widgets page as an example. Figure 1 shows a very simple ASP.NET 2.0 application in Solution Explorer.
By default, the Widget.aspx page will be accessible at ~/Products/W/Widget.aspx (where the tilde character, ~, stands for the root of the Web site). What's new in ASP.NET 2.0 is that you can change this by making an entry in the application's web.config file. To do this, you need to add a <urlMappings> section inside of the <system.web> section. Here's an example to do the mapping that we want:
<system.web> <urlMappings enabled="true"> <add url="~/Widget/aspx" mappedUrl="~/Products/W/Widgets.aspx"/> </arlMappings> </system.web>
Inside of the <urlMappings> element you can have as many <add> elements as you like. Each of these contains a url attribute, which specifies the URL that the user will enter, and a mappedUrl attribute, which specifies the actual URL within the application to deliver in place of the entered URL. Figure 2 shows the result of the user entering the specified URL in this case.
Note that even though ASP.NET has delivered the mapped URL, the URL entered by the user still shows in the browser's address bar.
The Limits of URL Mapping
The major limit of URL mapping, as it's implemented in ASP.NET 2.0, is that it's purely a static technique, with no wildcards in the mapping. You can include a querystring in the url (for example, you could map ~/Products/Widget.aspx to ~/Products.aspx?ProductID=widget) but you can't set up a single mapping that will use a regular expression to change all similar input URLs into similar mapped URLs. For many applications this is a severe, almost crushing limitation that impairs the utility of URL mapping considerably.
Why this limit? Microsoft's Scott Guthrie explained in a blog entry that the company plans to offer full-featured URL rewriting in IIS 7.0, which is scheduled to ship as part of Longhorn Server. With that implementation coming in a couple of years, it didn't make sense for the ASP.NET 2.0 team to do a partial implementation that could be subject to security and scalability problems for this release.
Flexible URL Rewriting Now
Fortunately you don't have to wait for the release of Longhorn Server to get more flexible URL rewriting. There are a couple of solutions available now that can help you if you need regular expressions in ASP.NET 2.0 URL rewriting today.
For starters, various ASP.NET developers have implemented their own HTTP modules for URL rewriting with RegEx support. Of the ones that I've seen, the most complete support for other ASP.NET 2.0 features (such as themes) is in the UrlRewritingNet namespace from Albert Weinert and Thomas Bandt. This free open source component is still configured by writing rules in the web.config file, but now the rules can use regular expressions for matching and replacement. For example, here's a valid rule using this component:
<rewrites> <add virtualUrl="^~/(.*)/(.*).aspx" rewriteUrlParameter="StoreInContextItems" destinationUrl="~/$2.aspx?language=$1¶meter=$2" ignoreCase="true" /> </rewrites>
This rule would map a URL such as ~/English/Add.aspx to ~/Add.aspx?language=English¶meter=add.
For additional flexibility, you may want to look at the commercial ISAPI_rewrite URL manipulation engine. One of the issues with HTTP module solutions is that these solutions only work on aspx files (or other files that are passed to the ASP.NET engine for evaluation). Because it's implemented as an ISAPI filter, ISAPI_rewrite can manipulate any URL that is sent to IIS. This allows you to apply regular expression-based rewriting to all file types. For example, if you needed to relocate image files or map .html URLs to .aspx pages with querystring parameters, this tool could do the job. ISAPI_rewrite comes in a lite testing version and a commercial ($69) version that can handle multiple sites on a single server.
A Technique Worth Knowing
URL rewriting is a useful tool to have in your bag of tricks. The best way to think of it is as a way to decouple the physical arrangement of your site from its logical presentation to the site's users. With URL rewriting, you can hand out short, friendly URLs for people to browse, and still use long, descriptive, well-organized URLs in your source code tree.
Depending on the complexity of your URL rewriting needs, you may or may not find Microsoft's native implementation in ASP.NET 2.0 sufficient. If you need more flexibility, evaluate some of the other alternatives I've pointed out in this article. You'll probably find that one of them can do the job for you.
About the Author
Mike Gunderloy is the author of over 20 books and numerous articles on development topics, and the Senior Technology Partner for Adaptive Strategy, a Washington State consulting firm. When he's not writing code, Mike putters in the garden on his farm in eastern Washington state.