How To: Use URL Rewriting in ASP.NET
URL rewriting is the practice publishing a cleaner URL for your ASP.NET web application. There are many reasons you might want to do this, chief amongst them being search engine optimization and human readability. This article will show you how to use URL rewriting to hide your ugly URL while retaining the power and structure of your existing ASP.NET application.
What is URL rewriting and why should I care?
As I said before, URL rewriting is a practice that lets you publish a cleaner URL to the world, but that may not be clear. In other words, you can "point" or redirect any URL a user accesses to an existing ASP.NET page in your application. Take a look at this URL:
http://www.joshjordan.com/index.php?i=321
That is my standard, ugly URL. Now look at this one, which is the result of URL rewriting:
http://www.joshjordan.com/google-chrome-beta-20-released-321
Which one looks better to your eye? Probably the second one. It gives the user some important information about what might be on that page. Which one looks better to a search engine? Definitely the second one. Search engines actively try to ascertain information about the contents of a page based on many criteria, and the URL is no exception. Google, Yahoo, and Live Search all pull common keywords out of the URL, and if you want traffic on your site (and lets face it, who doesn't?), you want to have a good page ranking with these search engines. Search engine optimization is a rapidly changing field, but providing search engine-friendly URLs is a practice that is going to consistently drive traffic to your site by making your page's search relevancy higher.
One worry that you may have is that we are only redirecting the user to a new page with URL rewriting. This would result in a few problems. Firstly, the URL shown in the user's browser would change to the ugly URL as soon as the access the page, and thus, our highly-guarded secret is exposed. Worse, they might link that URL to another person, which means they are giving out the ugly URL, and our effort would've been wasted. Finally, a search engine would see both the clean URL and the ugly URL, which could result in splitting your page ranking between the two of them. Don't worry, your ugly URL will not be exposed. URL rewriting in ASP.NET (at least the way I'll show you) does not redirect the HTTP request to another page, it actually answers the request at the clean URL with one from whatever page you'd like, all without any knowledge of the rewriting on the user's side.
Okay, URL rewriting is a good idea. How do I do it?
Well, that's simple. Just call the HttpContext.RewritePath() method from the Application_BeginRequest() event handler in your Global.asax file. What is that you say? You don't have a Global.asax file? Okay, I'll walk you through an example.
I am currently working on a project where my site has a county-based taxonomy. That is, the main page for a county is the primary unit of organization. Thus, I want to provide a provide a URL that includes the name of the county. Unfortunately, my otherwise well-designed data driven application will only provide me with something like this by default:
http://www.myproject.com/County.aspx?ID=5
However, I'd like it to look something more like this (for my home county of Rensselaer):
http://www.myproject.com/Rensselaer
I could, of course, just make a directory or Aspx page for Rensselaer, but I already have my application working so nice and cleanly! I don't want to create more pages that I have to maintain. So, I choose to use URL rewriting to handle this situation.
To get started with URL rewriting, create a Global.asax file. A Global.asax file is a set of event handlers for application-level events, such as client sessions beginning, client sessions ending, and (ah-ha!) URL requests beginning. To create this file, add a new file to your project and select Global Application Class. Leave the filename to its default.
Note that you will be unable to select Global Application Class if a Global.asax file already exists in your project. Now that we have this file, we want to add code to the Application_BeginRequest() event handler that handles our URL rewriting. In this example, I will simply route based on the contents of the incoming URL. If the URL contains one of my keywords, I will route it appropriately. If not, I will do nothing and the request will be processed normally (either landing on some existing page, or producing a 404 error).
protected void Application_BeginRequest(object sender, EventArgs e)
{
//Friendly URL keywords
string[] counties = { "Albany", "Rensselaer", "Montgomery" };
//Loop through keywords
for(int i=0; i<counties .Length; i++)
{
//Check to see if the URL contains this keyword
//Remember to use case-insensitive logic!
if (Request.Url.ToString().ToLower().Contains(counties[i]))
{
//If a keyword was found, rewrite and break out
Context.RewritePath("~/County.aspx?CountyID=" + i);
return;
}
}
}
I use the string.Contains() method and a string array in this simple example. I route to the indices of the string in the array. Note that the incoming URL could have a mix of capital and lowercase letters, so you should always use string.ToLower() when performing comparisons in this case. In a more realistic example, a Dictionary of strings and integer ID's may be necessary, or even a connection to a database to retrieve keywords. Some useful objects you should play with to extract data from the incoming request:
- Request.URL: The entire incoming URL, used above.
- Request.QueryString: The parameters, provided as key-value pairs, beyond the "?" in the URL. Note that this object has string and int-based indexers.
- Request.URL.ToString().Split('/'): A string array split into tokens based on forward slashes. This is useful because it allows you to look at the individual directories and files requested beyond the domain.
Advanced Routing
Since you can write any code you like in the Application_BeginRequest() method, there is a lot you can do here. As I mentioned, you could use values from a database, or parse the URL into multiple different pieces to control your routing. If there is sufficient demand, I will write another few articles that talk about advanced topics in URL rewriting, touching up on those topics as well as setting up virtual directories, preserving the query string, handling image requests by wrapping them with HTML, efficiency in URL rewriting, etc. Please give me some feedback if you want more!
Other URL rewriting methods for ASP.NET
Other methods exist for URL rewriting, but I didn't mention them here both because I haven't tried them and because they seem much less ideal than the solution I gave above. If you are looking for other ways to do this, be on the look out for rewriting using the Request.PathInfo object, which uses a URL that looks something like this (which is still ugly to me):
http://www.myproject.com/county.aspx/Rensselaer
There are Web.config approaches, but they are less programmatic and do not give you dynamic control over your routing. I want to write code to do this! If I was doing it statically, I might as well just use new Aspx pages. Finally, you can use ISAPIRewrite to have your IIS server do the routing for you. Again, this is too static for me. For more information on these approaches, check out this amazing post on Scott Guthrie's blog.
Notes
I just wanted to point out what a big deal URL rewriting is becoming these days by pointing out that it is one of the main concepts behind the ASP.NET MVC framework approach. Every ASP.NET MVC tutorial I've seen has started with the routing module, which provides a facility for automatically tokenizing the URL into separate pieces to decide how to route the request to the View, including default values for each piece. Can you tell I'm excited about ASP.NET MVC?


Subscribe to this category
"Which one looks better to your eye? Probably the second one. It gives the user some important information about what might be on that page. Which one looks better to a search engine? Definitely the second one."
Then why should you even bother with URL rewriting if both concerned parties prefer the second choice?
March 26th, 2009 at 12:12 PM
Well, there are many more parties concerned with your application than just the user and a search engine. The developer and the developer's organization are also major players. Plain and simple, it is generally much easier (read: faster, more robust, and less error-prone) to structure your application in such a way that it revolves around receiving numeric IDs in the querystring rather than "prettified" URLs. As mentioned in the article, URL rewriting prevents you from having to create a separate Aspx page for each friendly URL that you want to accept.
Perhaps I misunderstood the question. If the second choice you are referring to is the result of URL rewriting, why not bother with URL rewriting?
March 26th, 2009 at 12:18 PM
I just wanted to point out that there is no difference to doing what you propose above with an HttpModule and your Global.asax code. With the HttpModule approach, you'd simply tie into the Application.BeginRequest event and go from there. Either way the code is firing during the same event...
March 27th, 2009 at 8:01 AM
James,
You're absolutely right. What I meant to say was that there are HttpModule approaches that can be linked up through the Web.config file that are less dynamic. Indeed, the Global.asax approach really is an HttpModule approach. Thanks for the clarification.
March 27th, 2009 at 9:10 AM