Jun 09

The MVC routing assembly – part IV

Posted in ASP.NET MVC      Comments Off on The MVC routing assembly – part IV

In the previous posts, we’ve talked about Routes. Today, we’re see how we can register the routes on a ASP.NET web application.

Currently, a colecction of routes is represented through an element of type RouteCollection. If you fire up Reflector and start looking at this class, you’ll see that a RouteCollection is just a specialized version of the Collection<RouteBase> type.

In fact, if you take a closer look at the class, you’ll see that it just ends up adding a couple of methods and then it will simply override others inherited from the base class. Here’s a list of the new methods that have been added:

  • GetRouteData: you can use this method to get a reference to a RouteData element associated with the current context. Internally, the method goes over all the routes maintained in its internall collection, calling the GetRouteData over each of those instances. When it finds a valid route (ie, when one of those methods returns a non-null value), it simply returns that value;
  • GetVirtualPath: as you might expect by now, this method will return the Virtual Path associated with the current request (when one is available). Internally,it does a similar job tothe GetRouteData method; the only differente is that it will call the GetVirtualPath method over each registered route (instead of the GetRouteData method);
  • Add: the class introduces an overload of the Add method. Instead of simply receiving a route,with this class you’ll be able to associate a name with a specific route. When you use this method, you end up saving a reference to the route on the internal collection maintained by the base class and you’ll also save a reference to that element on a dictionary defined by the RouteCollection class. In practice, this means that you can also get a route by name quickly.

Besides these methods, the class introduces some utility methods that will let you control the lock in the collection. I’m talking about the GetReadLock and GetWriterLock methods. These methods are used internally to garantee that the route collection plays well in  muthithreaded scenarios. Since these methods are public, this means that you should call them if you decide to go through all the routes stored on a collection by using a foreach loop. Notice that you don’t need to do that if you use the methods presented in the previous list since those methods already take the appropriate locks. You can read more about the locking mechanism on Eilon’s blog.

Ok, now that we know how to store several routes, we need to talk about how to add a collection of routes to a web app. In the current release, you add routes by accessing the static Routes property exposed by the RouteTable class. Generally, you’ll add routes during the application start event. Here’s a quick example:

RouteTable.Routes.Add( “route1”,
       new Route( “foo/{anything}”, new MvcRouteHandler() ) );
RouteTable.Routes.Add( “route2”,
       new Route( “foo/{lang}-{locale}/{anything}”, new MvcRouteHandler() )

Notice that I’m not setting any defaults or constraints on the previous Routes (though I could have done that).

If you’re using the the MVC platform, then you’ll be glad to know that the System.Web.Mvc assembly introduces several extension methods that will reduce the code necessary to add Routes to the RouteTable. After adding the correct namespace:

using System.Web.Mvc;

you’ll be able to access the following extension methods:

public static class RouteCollectionExtensions
    public static void MapRoute(this RouteCollection routes, string name, string url);
    public static void MapRoute(this RouteCollection routes, string name, string url, object defaults);
    public static void MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints);

In practice, this means that you can write the previous rules like this:

RouteTable.Routes.MapRoute( “route1”, “foo/{anything}” );
RouteTable.Routes.MapRoute( “route1”, “foo/{lang-locale}/{anything}” );

Internally, those methods will end up creating the routes and associating them with the MvcRoutingHandler (which, as we’ll see in a future post, is responsible for getting the correct handler for MVC requests). Notice that there are also other overloads that will let you sepcify the defaults and the constraints applied to a specific route, as you can see by looking at the previous extension methods’ signatures.  

In the next post we’ll see how these routes are processed and we’ll talk about the UrlRouting module. Stay tunned.