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
- public
class
Product
- {
- public
string Category {
get;
set;}
- public
string ProductID {
get;
set;}
- }
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:
- var productRoute =
new
Route("products/{Category}/{ProductID}",
typeof (Product));
-
- var configuration =
new
RouterConfiguration();
- configuration.Routes.Add(productRoute);
- var router =
new
Router(configuration);
-
- var product = (Product)router.ResolveUrl("products/beverages/7");
And having product instance, router can translate it to url
- var productRoute =
new
Route("products/{Category}/{ProductID}",
typeof (Product));
-
- var configuration =
new
RouterConfiguration();
- configuration.Routes.Add(productRoute);
- var router =
new
Router(configuration);
-
- var url = router.GetUrl(new
Product {Category =
"beverages", ProductID = 7});
- 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
- public
class
Category
- {
- public
string Name {
get;
set;}
- }
-
- public
class
Product
- {
- public
Category Category {get;set;}
- public
int ProductID {
get;
set;}
- }
We can create two routes categoryRoute and productRoute
- var categoryRoute
= new
Route("products/{Name}",
typeof (Category));
- var productRoute =
new
Route("{Category}//{ProductID}",
typeof (Product));
- categoryRoute.ChildRoutes.Add(productRoute);
-
- var configuration =
new
RouterConfiguration();
- configuration.Routes.Add(categoryRoute);
- var router =
new
Router(configuration);
-
- Product product = (Product)router.ResolveUrl("products/beverages/7");
- 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.
- <configuration>
- <configSections>
- <section
name="LiveUI.Routing"
-
type="Xtensive.Web.Applications.RoutingConfigurationSection,
Xtensive.Web.Applications"/>
- ...
- <LiveUI.Routing>
- <routes>
- <add
name="category"
format="products/{Name}"
targetType="Demos.Category,
Demos">
- <routes>
-
<add
name="product"
format="{ProductID}"
-
targetType="Demos.Product,
Demos"
-
handler="~/MyPage.aspx"
/>
- </routes>
- </add>
- </routes>
- </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
- <httpModules>
- <add
name="LiveUI.Error404-Handler"
type="Xtensive.Web.Deployment.Error404RedirectModule,
Xtensive.Web" />
- </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
- <httpModules>
- <add
name="LiveUI.Error404-Handler"
type="Xtensive.Web.Deployment.Error404RedirectModule,
Xtensive.Web" />
- </httpModules>
|