Using ASP.NET Routing Independent of MVC

One of the demos I've been doing at the MSDN Roadshow is to take the new ASP.NET routing capabilities (currently in preview) and show them in isolation from MVC / Dynamic Data. Although the new routing capabilities were developed for the MVC framework, they've been factored out and are now shared with Dynamic Data and, of course, you can use them in your own ASP.NET applications as well.

What do these new routing capabilities give you? Flexibility for one. Each request is intercepted and matched against a pre-populated RouteTable for a pattern match. Assuming a match is found, the designated RouteHandler is invoked to handle the request. The job of the RouteHandler is to take whatever action is required and ultimately return an IHttpHandler which will be used to render the response to the client. So we have something like:

 image

Let's try and build the simplest of ASP.NET applications taking advantage of the new routing capabilities. To do this you will need Visual Studio 2008 / ASP.NET 3.5 and I am using the 0408 release of Dynamic Data to provide the routing capabilities. There are various flavours around (from MVC and Dynamic Data), you might just have to change things slightly to get them working.

  • Start with a new ASP.NET 3.5 website
  • Add a reference to the System.Web.Routing dll. I am using the version that ships with the 0408 Release of Dynamic Data. To add a reference, Browse to the location where the Dynamic Data Runtime and Templates are installed

image

  • Add a Global Application Class (Global.asax) file to the website

image

  • In Global.asax we can hook into the Application_Start() method to pre-populate our routing information. We're going to do something very simple and look for pattern that matches just a single string (no delimeters)
 <%@ Application Language="C#" %>
<%@ Import Namespace="System.Web.Routing" %>

<script RunAt="server">

    void Application_Start(object sender, EventArgs e)
    {
        RegisterRoutes(RouteTable.Routes);
    }

    private void RegisterRoutes(RouteCollection Routes)
    {
        Route r = new Route("{Parameter}", new MEOSimpleRouteHandler());
        Routes.Add(r);
    }
    
</script>
  • This follows a similar pattern used by the MVC and Dynamic Data templates - we have a RegisterRoutes() method that takes a RouteCollection and call that method passing the RouteTable.Routes property (a static property).
  • We create a new Route, the first parameter is the URL pattern we want to match and the second is an IRouteHandler we want to be responsible for handling the request. Then we add that route the the RouteCollection.
  • MEOSimpleRouteHandler is an IRouteHandler we're going to create now
  • Add an App_Code folder to the website and create a new class called MEOSimpleRouteHandler
  • The class must implement IRouteHandler which means implementing a single method GetHttpHandler which returns an IHttpHandler.
  • Our code will be the following:
 using System.Web.Routing;
using System.Web;
using System.Web.UI;
using System.Web.Compilation;

public class MEOSimpleRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        string pageName
            = requestContext.RouteData.GetRequiredString("Parameter");

        pageName =
            pageName.ToLower() == "home" ? "default" : pageName;

        string virtualPath
            = string.Format("~/RoutingDemoPages/{0}.aspx", pageName);

        return (Page)BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page));
    }
}

Our implementation of the GetHttpHandler() method firstly extracts a parameter (I've called it Parameter) from the URL. We do this by calling GetRequiredString() on the RouteData object in the requestContext. By virtue of the fact that we enclosed "Parameter" in curly braces in the Route pattern, it is treated as a parameter in the URL rather than a static string to be matched.

Having done that I do one simple manipulation (you get as clever / fancy as you like here) which is to say that if the user has requested "home" as the URL then it gets converted to "default". ie requesting "home" or "default" will give the same result. I then create a virtualPath to the aspx page I'm going to serve up as the IHttpHandler instance.

The virtual path is set to ~/RoutingDemoPages/[Parameter].aspx. So whatever is requested as a URL, our RouteHandler tries to serve up as an aspx page from the RoutingDemoPages folder. Finally, the BuildManager class  allows us to create an instance of the Page class at that virtual path.

So we need to add a RoutingDemoPages folder to our website and populate it with a few aspx pages. Let's say we add Page1.aspx, Page2.aspx, Page3.aspx and default.aspx. Add some unique content to each page so you know when it's being served.

image

There's one last thing we need to do to get this site working - we need to add the UrlRoutingModule into the httpModules section in web.config (in the system.web section).

image

We should be good to go. Set the start page for the website to / (in website properties Start Options tab) and hit F5 to start debugging.

image

In your browser, from the site root, add "default" to the URL, for me that looks like https://localhost:63240/WebSite3/default (I'm using the Visual Studio built-in webserver) and you'll find that the default.aspx page in the RoutingDemoPages folder is served up. Change default to home, Page1, Page2 etc and confirm these pages are also served. Maybe place a breakpoint in the RouteHandler code just to confirm that the code is executed on each request.

Technorati Tags: asp.net,mvc,routing,msdn roadshow