In these last 2 days I’ve been looking at the internals of the System.Web.Routing assembly. I’ve thought about writing some posts with several notes on how it works so that I have a future reference when I need it. Putting it here on my blog will make it easy to find these notes and it may even help the guys that are starting out (but that are a little behind me right now).
In this post, I’ll just present the basics (and there really isn’t much to say, believe me). The routing assembly is based on three or four basic types + a module which is responsible for intercepting the requests and performing the mapping magic. But lets start with those three or four basic types…
The RouteBase type is (arguably) one of the most important types you’ll find on this assembly. It’s main objective is to define the contract that all routes must implement (normally, you’ll end up using the derived Route class in your programs). Currently, the class defines the following contract:
public abstract class RouteBase
public abstract RouteData GetRouteData(HttpContextBase httpContext);
public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
As you can see, each concrete route type must implement two methods: GetRouteData and GetVirtualPath. The first (GetRouteData) is used (indirectly) by the UrlModule (which will be presented in a future post) to get info associated with the current request. The RouteData object returned by this method has all the necessary info about the current route. At this time, it’s important to note that if none of the pre-registered routes (you’ll see more on this when we talk about the RouteTable class) return a valid value from this method, then the routing framework won’t do anything and the request will end up beeing handled like if the routing platform didn’t exist.
Now, when there’s a route which matches the current url request and you have a valid RouteData object, that instance will be used for getting an IRouteHandler associated with the current route. The IRouteHandler has the following signature:
public interface IRouteHandler
IHttpHandler GetHttpHandler(RequestContext requestContext);
As you can see, the main objective of an IRouteHandler is to return and IHttpHandler that will process the request. Notice that the GetHttpHandler will receive an instance to the current RequestContext,which should be propagated to the handler that will end up processing the request. This class (RequestContext) has two properties which will give you the current RouteData and the ASP.NET wrapped context (property HttpContext – for more info on these wrappers,check my previous post on the subject).
It’s now time to look at the GetVirtualPath method exposed by the RouteBase class. The main objective of this method is to return an instance of the VirtualPathData associated with this request. You won’t normally be using this method if you’re going to use the MVC approach. On the other hand, it might be really important if you want to use the routing module with the Web Forms approach (just download the MVC preview code and take a look at the Futures folder).
Ok, so in this post we’ve already introduced several topics:
- the RouteCase class sets up the basic contract that all route types must implement;
- we’ve seen that there are some utility classes that will help propagating the route information along the ASP.NET pipeline (RouteData and RequestContext are two classes that do just that);
- when using routing, the request will be intercepted by a HTTP module (UrlModule) which will do its magic and reuse the contract defined by the RouteBase class to forward the request to an IRouteHandler;
- The IRouteHandler is there so that you can easilly forward the current RequestContext to an HTTP handler (IHttpHandler) that should be used to handle the request.
In the next post, we’ll look at the use of routes and route tables.