Saturday, June 26, 2010

Url Rewriting with ASP.NET,C#

People often ask me for guidance on how they can dynamically "re-write" URLs and/or have the ability to publish cleaner URL end-points within their ASP.NET web applications. This blog post summarizes a few approaches you can take to cleanly map or rewrite URLs with ASP.NET, and have the option to structure the URLs of your application however you want.

Why does URL mapping and rewriting matter?
The most common scenarios where developers want greater flexibility with URLs are:

1) Handling cases where you want to restructure the pages within your web application, and you want to ensure that people who have bookmarked old URLs don't break when you move pages around. Url-rewriting enables you to transparently forward requests to the new page location without breaking browsers.

2) Improving the search relevancy of pages on your site with search engines like Google, Yahoo and Live. Specifically, URL Rewriting can often make it easier to embed common keywords into the URLs of the pages on your sites, which can often increase the chance of someone clicking your link. Moving from using querystring arguments to instead use fully qualified URL's can also in some cases increase your priority in search engine results. Using techniques that force referring links to use the same case and URL entrypoint (for example: weblogs.asp.net/scottgu instead of weblogs.asp.net/scottgu/default.aspx) can also avoid diluting your pagerank across multiple URLs, and increase your search results.

In a world where search engines increasingly drive traffic to sites, extracting any little improvement in your page ranking can yield very good ROI to your business. Increasingly this is driving developers to use URL-Rewriting and other SEO (search engine optimization) techniques to optimize sites (note that SEO is a fast moving space, and the recommendations for increasing your search relevancy evolve monthly). For a list of some good search engine optimization suggestions, I'd recommend reading the SSW Rules to Better Google Rankings, as well as MarketPosition's article on how URLs can affect top search engine ranking.

Sample URL Rewriting Scenario
For the purpose of this blog post, I'm going to assume we are building a set of e-commerce catalog pages within an application, and that the products are organized by categories (for example: books, videos, CDs, DVDs, etc).

Let's assume that we initially have a page called "Products.aspx" that takes a category name as a querystring argument, and filters the products accordingly. The corresponding URLs to this Products.aspx page look like this:

http://www.store.com/products.aspx?category=books
http://www.store.com/products.aspx?category=DVDs
http://www.store.com/products.aspx?category=CDs
Rather than use a querystring to expose each category, we want to modify the application so that each product category looks like a unique URL to a search engine, and has the category keyword embedded in the actual URL (and not as a querystring argument). We'll spend the rest of this blog post going over 4 different approaches that we could take to achieve this.

Approach 1: Use Request.PathInfo Parameters Instead of QueryStrings

The first approach I'm going to demonstrate doesn't use Url-Rewriting at all, and instead uses a little-known feature of ASP.NET - the Request.PathInfo property. To help explain the usefulness of this property, consider the below URL scenario for our e-commerce store:

http://www.store.com/products.aspx/Books
http://www.store.com/products.aspx/DVDs
http://www.store.com/products.aspx/CDs
One thing you'll notice with the above URLs is that they no longer have Querystring values - instead the category parameter value is appended on to the URL as a trailing /param value after the Products.aspx page handler name. An automated search engine crawler will then interpret these URLs as three different URLs, and not as one URL with three different input values (search engines ignore the filename extension and just treat it as another character within the URL).

You might wonder how you handle this appended parameter scenario within ASP.NET. The good news is that it is pretty simple. Simply use the Request.PathInfo property, which will return the content immediately following the products.aspx portion of the URL. So for the above URLs, Request.PathInfo would return "/Books", "/DVDs", and "/CDs" (in case you are wondering, the Request.Path property would return "/products.aspx").

You could then easily write a function to retrieve the category like so (the below function strips out the leading slash and returning just "Books", "DVDs" or "CDs"):

Function GetCategory() As String

If (Request.PathInfo.Length = 0) Then
Return ""
Else
Return Request.PathInfo.Substring(1)
End If

End Function
Sample Download: A sample application that I've built that shows using this technique can be downloaded here. What is nice about this sample and technique is that no server configuration changes are required in order to deploy an ASP.NET application using this approach. It will also work fine in a shared hosting environment.

Approach 2: Using an HttpModule to Perform URL Rewriting
An alternative approach to the above Request.PathInfo technique would be to take advantage of the HttpContext.RewritePath() method that ASP.NET provides. This method allows a developer to dynamically rewrite the processing path of an incoming URL, and for ASP.NET to then continue executing the request using the newly re-written path.

For example, we could choose to expose the following URLs to the public:

http://www.store.com/products/Books.aspx
http://www.store.com/products/DVDs.aspx
http://www.store.com/products/CDs.aspx
This looks to the outside world like there are three separate pages on the site (and will look great to a search crawler). By using the HttpContext.RewritePath() method we can dynamically re-write the incoming URLs when they first reach the server to instead call a single Products.aspx page that takes the category name as a Querystring or PathInfo parameter instead. For example, we could use an an Application_BeginRequest event in Global.asax like so to do this:

void Application_BeginRequest(object sender, EventArgs e) {

string fullOrigionalpath = Request.Url.ToString();

if (fullOrigionalpath.Contains("/Products/Books.aspx")) {
Context.RewritePath("/Products.aspx?Category=Books");
}
else if (fullOrigionalpath.Contains("/Products/DVDs.aspx")) {
Context.RewritePath("/Products.aspx?Category=DVDs");
}
}
The downside of manually writing code like above is that it can be tedious and error prone. Rather than do it yourself, I'd recommend using one of the already built HttpModules available on the web for free to perform this work for you.

Source of this blog @ http://weblogs.asp.net/scottgu/archive/2007/02/26/tip-trick-url-rewriting-with-asp-net.aspx

No comments: