ASP.NET - Using Routes to map extensionless SEO-Friendly Urls

How to use System.Web.Routing to perform both simple and complex extensionless Url Rewriting in ASP.NET Applications.

In previous articles I've described how to use the IIS Url Rewrite Module to map both database lookups and REGEX rules to extensionless SEO-Friendly Urls. But there is another way to perform this kind of trick.

Early in the development of ASP.NET MVC Microsoft realized that the System.Web.Routing infrastructure was not only applicable to ASP.NET MVC, but could be used in any ASP.NET application to allow for much easier url rewriting.

System.Web.Routing has two basic concepts; the concept of a route and that of a route handler.

A route is simply a class that holds a pattern which can be matched to inbound requests. Each request is matched against the list of Routes that you have defined, and if one matches then that route is used.

The route handler can be a page, web service, ASHX handler or any other type of request handler that accepts and processes the routed request.

This means you can have SEO-Friendly URLs in an ASP.NET application that look like this:

http://yourapp.com/ExpenseReportDetail/US/2011/page and stuff


The route for the above looks like this:

routes.MapPageRoute("ExpenseDetailRoute",
"ExpenseReportDetail/{locale}/{year}/{*queryvalues}", "~/Expense.aspx",
false,
new RouteValueDictionary { { "locale", "US" }, { "year", DateTime.Now.Year.ToString() } },
new RouteValueDictionary { { "locale", "[a-z]{2}" }, { "year", @"\d{4}" } },
new RouteValueDictionary { { "account", "1234" }, { "subaccount", "5678" } });

The first parameter is just a name for the route, which can be most anything you want.

The second parameter maps the url of a pseudo-folder "/ExpenseReportDetail/" plus additional parameters in the form of "folders". In this case those "folders" are {year}, and {queryvalues}. Note that the asterisk at the beginning of the definition {*queryvalues} is a wildcard - it means if there is nothing in that place, it still maps, but will have a null value.

Note also that a RouteValueDictionary consisting of a locale and a year, both having default values, has been added. Also, there are DataTokens added for an account and a subaccount, both with default values. These routes can of course be set up dynamcially based on some logic at runtime as well.

The third parameter specifies the handler - in this case, the "/Expense.aspx" page.
The fourth parameter tells whether to check physical Url access,
and the fifth parameter represents a RouteValueDictionary.
The sixth parameter defines any constraints (in this case Regular Expressions for the locale and the year).
The last parameter defines any data tokens we wish to send to the respective handler.

In the receiving ASP.NET page that these are mapped to, we can get all these values with code like the following:

protected void Page_Load(object sender, EventArgs e)
{
string locale =(string) Page.RouteData.Values["locale"];
string year = (string) Page.RouteData.Values["year"];
string queryValues = (string) Page.RouteData.Values["queryvalues"];
string account = (string)Page.RouteData.DataTokens["account"];
string subaccount = (string)Page.RouteData.DataTokens["subaccount"];
label1.Text = locale + ": " + year + ": " + queryValues + ": " + account + " : " + subaccount;

// At this point you would probably do a database lookup with your parameters and display information based on it.
}

This all makes for a very "clean" UrlRewriting scheme that search engines like a lot, especially if the folder names have important keywords in them.

There are other programmatic constructs in System.Web.Routing - the Route class has four overloaded constructors, HttpMethodConstraint class, the PageRouteHandler class, and others, including the RequestContext, which exposes both the HttpContext and the RouteData.

With all the classes in System.Web.Routing, it is possible to get quite sophisticated; the short demo solution you can download here only covers the basics.

Routes are typically set up in the Application_Start global.asax method by making a call to a method that establishes the routes. You can see an example of this in the downloadable solution.

By Peter Bromberg   Popularity  (3038 Views)