Routing in ASP.NET.

Introduction

It goes without saying that proffessional web applications should have user friendly urls. On the one hand nice urls help navigation and search engine optimiztion on the other hand they allow developers to change web application internals without breaking users' bookmarks. Ideally url format should be fully configurable and application should not break when url configuration is changed. LiveUI Routing does exactly that. This document describes how LiveUI routing works and how to use it.

Basics

Technically, LiveUI routing makes convertion from url to .net object and vice-versa. This convertion is performed by Router class which shoud be configured using .config file or manually. Router configuration is just set of rules describing how to map .NET type and url. For example, if we have Product class

  1. public class Product
  2. {
  3.   public string Category { get; set;}
  4.   public string ProductID { get; set;}
  5. }

We can specify format "products/{Category}/{ProductID}" and Router would convert url "products/beverages/7" to Product instance and back. There is an code sample illustrating this:

  1. var productRoute = new Route("products/{Category}/{ProductID}", typeof (Product));
  2.  
  3. var configuration = new RouterConfiguration();
  4. configuration.Routes.Add(productRoute);
  5. var router = new Router(configuration);
  6.  
  7. var product = (Product)router.ResolveUrl("products/beverages/7");

And having product instance, router can translate it to url

  1. var productRoute = new Route("products/{Category}/{ProductID}", typeof (Product));
  2.  
  3. var configuration = new RouterConfiguration();
  4. configuration.Routes.Add(productRoute);
  5. var router = new Router(configuration);
  6.  
  7. var url = router.GetUrl(new Product {Category = "beverages", ProductID = 7});
  8. Assert.AreEqual("products/beverages/7", url);

Route class decribes mapping between .net type and url, route also allows customization of how instance should be created.

Route composition

LiveUI routing also supports composition of routes. If url consists of several logically independent fragments it's better to create serveral routes and combine them. For example, having two classes

  1. public class Category
  2. {
  3.   public string Name { get; set;}
  4. }
  5.  
  6. public class Product
  7. {
  8.   public Category Category {get;set;}
  9.   public int ProductID { get; set;}
  10. }


We can create two routes categoryRoute and productRoute
  1.  var categoryRoute = new Route("products/{Name}", typeof (Category));
  2.  var productRoute = new Route("{Category}//{ProductID}", typeof (Product));
  3.  categoryRoute.ChildRoutes.Add(productRoute);
  4.  
  5.  var configuration = new RouterConfiguration();
  6.  configuration.Routes.Add(categoryRoute);
  7.  var router = new Router(configuration);
  8.  
  9.  Product product = (Product)router.ResolveUrl("products/beverages/7");
  10.  Assert.IsTrue(product.Category.Name=="beverages");

Route format basics

Routing format supports following syntax constructions:

  • category//{Product} (for  Category)
    In this case Product instance will be assigned to Product property of Category instance.
  • {Category}//{productID} (for Product)
    In this case Product instance will be assigned to Category property of Product instance.
  • ?product=/{productID} (for Product)
    In this case ProductID can be passed as parameter.
  • ({CategoryName}/)* (for Category)
    If Category.Name property were  of type string[] or StringCollection then it would Router would also translate urls like  "food/beverages/pepsi/..."

Using Routing in ASP.NET applications

LiveUI provides default Router for url rewriting in ASP.NET applications. This router is accessible through module  RoutingModule.Router and can be configured manually, it also can be configured using configuration section.

  1. <configuration>
  2.   <configSections>
  3.     <section name="LiveUI.Routing"
  4.              type="Xtensive.Web.Applications.RoutingConfigurationSection, Xtensive.Web.Applications"/>
  5. ...
  6. <LiveUI.Routing>
  7.   <routes>
  8.       <add name="category" format="products/{Name}" targetType="Demos.Category, Demos">
  9.       <routes>
  10.         <add name="product" format="{ProductID}"
  11.              targetType="Demos.Product, Demos"
  12.              handler="~/MyPage.aspx" />
  13.       </routes>
  14.     </add>
  15.   </routes>
  16. </LiveUI.Routing>

If handler attribute is specified for route  (handler="~/MyPage.aspx") then request will be processed by handler specified. 

As url rewriting is performed by HttpModule it whould also be registered in web.config
  1. <httpModules>
  2.    <add name="LiveUI.Error404-Handler" type="Xtensive.Web.Deployment.Error404RedirectModule, Xtensive.Web" />
  3.  </httpModules>

Routing FAQ

  • How to tranform object to url using default router ?
    RoutingModule.CurrentRouter.GetUrl(new Product {ID = 7});


  • How to get current route  from httpHandler?
    var product = RoutingHttpModule.GetResolvedItem<Product>();


  • How to configure route manually ?
    The best method is to create new Module which would configure RoutingModule when applications starts.

  • Does routing work at older IIS versions ?
    Yes it does, but there might be problems because asp.net should process all web requests, which is not allways easy to achieve especially when application is deployed at virtual hosting. In this case following workaround can be used:
    Set Error404.axd as error 404 page url in IIS and add special module to configuration
    1. <httpModules>
    2.    <add name="LiveUI.Error404-Handler" type="Xtensive.Web.Deployment.Error404RedirectModule, Xtensive.Web" />
    3.  </httpModules>