ASP.NET MVC: Store Routes in the Database

Download the sample MVC project for this post
NOTE:  You should have ASP.NET MVC Preview 3 or later installed to run the provided download.

So far I’m a huge fan of the ASP.NET 3.5 MVC framework which is currently released as Preview 3.  Having worked with primarily Microsoft web frameworks MVC provides a refreshing perspective for what I consider an improved tier separation.

An immediate beef I have with ASP.NET MVC is defining the routes in the Global.asax.cs… I can’t change routes without recompiling and deploying code.  I thought it better to configure routes in a more dynamic environment, specifically the database, which is what this post will provide an example for.
I’ve broken the implementation into three main pieces: 

  1. Database schema for storing routes and route default parameters
  2. LINQ to SQL model for accessing the routes
  3. Class for handling route routines

 

Database Schema – “Mvc”

MvcRoutes Table

Routes table design

routeID
– the primary key for a route.
routeName – simply for identification purposes.  This isn’t used in the app.
routePattern – the URL structure of the route.
routeIsActive – turn your route on or off.
routeOrder – routes are executed on a first match basis.  It may be important to order your routes so a more specific pattern is caught first before a more general pattern catches it… similar logic to exception handling.


MvcRoutes Sample Data

Routes table data
 

MvcRouteParams Table

Route parameters table design

paramID
– the primary key and identifier for the route parameter.
routeID – foreign key to the MvcRoutes.RouteID value.
paramKey – route defaults are stored as a Dictionary.  This is the key for a default.
paramValue – the default value for the paramKey.
paramConstraint – a regular expression value specifying allowed values for the parameter
paramDataType – I’m actually not using this right now but it feels right to analyze the expected data type in a more complete sample… or somethingJ.

 

MvcRouteParams Sample Data

Route parameters table data
 

LINQ to SQL Model

The model is super simple… connect to your MVC routing database and drag the MvcRoutes and MvcRouteParams tables to a new LINQ to SQL class.
Route parameters table design
Now we can do some simple queries.
 

Route Helper Class – Routing.cs

The Routing.cs class provides a handful of methods for working with the RouteTable and interaction with the database.  In my project I included a new controller to handle resetting and displaying the routes which utilizes some of these additional methods.
 
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
 
using MvcAltRouting.Models;
 
namespace MvcAltRouting
{
    internal class Routing
    {
        public static RouteCollection Routes
        {
            get { return RouteTable.Routes; }
        }
 
        /// <summary>
        /// Gets the configured routes.
        /// </summary>
        /// <returns></returns>
        public static List<MvcRoute> GetConfiguredRoutes()
        {
            MvcRoutesDataContext db = new MvcRoutesDataContext();
            List<MvcRoute> dbRoutes = (from b in db.MvcRoutes
                                       where b.routeIsActive == true
                                       orderby b.routeOrder
                                       select b).ToList();
            return dbRoutes;
        }
 
        /// <summary>
        /// Clears current and readds application routes.
        /// </summary>
        public static void ResetAppRoutes()
        {
            Routes.Clear();
            SetAppRoutes();
        }
 
        /// <summary>
        /// Sets the application routes.
        /// </summary>
        public static void SetAppRoutes()
        {
            List<MvcRoute> configuredRoutes = GetConfiguredRoutes();
            SetAppRoutes(configuredRoutes);
        }
 
        /// <summary>
        /// Sets the application routes.
        /// </summary>
        /// <param name="configuredRoutes">Collection of routes to add to the application's routing table.</param>
        public static void SetAppRoutes(List<MvcRoute> configuredRoutes)
        {
            //add the routes to the RouteCollection
            foreach (MvcRoute route in configuredRoutes)
            {
                //create RouteValueDictionary objects to add the default values and contraints to the route
                RouteValueDictionary constraints = new RouteValueDictionary();
                RouteValueDictionary routeVals = new RouteValueDictionary();
 
                foreach (MvcRouteParam param in route.MvcRouteParams)
                {
                    routeVals.Add(param.paramKey, param.paramValue);
                    if (!string.IsNullOrEmpty(param.paramConstraint))
                    {
                        constraints.Add(param.paramKey, param.paramConstraint);
                    }
                }
 
                //create the route using the defaults set above
                RouteTable.Routes.Add(new Route(route.routePattern, new MvcRouteHandler())
                {
                    Defaults = routeVals,
                    Constraints = constraints
                });
            }
        }
    }
}
 

Global.asax.cs

Lastly change the Application_Start method to use the new Routing class to populate the application routes, removing the need for the routes defined within the Global.asax.cs.
using System;
 
namespace MvcAltRouting
{
    public class GlobalApplication : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            Routing.SetAppRoutes();
        }
    }
}


That’s It!

Start up the provided project and navigate to the “Display Routes” link.  You can see the routes have been set from the database values we saw from above!

Have you been working with the ASP.NET MVC framework?  If so have you moved the route configuration out of the Global.asax.cs or are you happy with the default configuration for editing routes?
 
Download the sample MVC project for this post
NOTE:  You should have ASP.NET MVC Preview 3 or later installed to run the provided download.

kick it on DotNetKicks.com
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Related posts

Comments

March 18. 2008 08:20 AM

pingback

Pingback from mhinze.com

Links Today (2008-03-18)

mhinze.com

March 18. 2008 09:40 AM

pingback

Pingback from blog.maartenballiauw.be

March 18 ASP.NET MVC links

blog.maartenballiauw.be

April 24. 2008 10:13 AM

pingback

Pingback from weblogs.asp.net

47 ASP.NET MVC Resources to Rock Your Development - Craig Shoemaker

weblogs.asp.net

June 9. 2008 12:31 PM

Tony

Any way you can update your sample code to run with MVC Preview 3?

Thanks,
Tony

Tony

June 25. 2008 08:25 AM

Roger Chapman

I've been working on ASP.NET MVC for quite some time now.
The first thing I do when I create a new MVC project is to move out the routing stuff in the Global.asax.cs to my own RoutesManger.cs
I like your idea of storing the routes in the database, however I'm not sure on a real need for this.
1. Once you have set up your routes there is not a huge need for this to be configurable. The only time you may change a route is the likelihood that you've added a new controller or action, in which case you would have to rebuild anyway.
2. You would have an extra "hit" against the database at the start of the application.
3. Any changes you made to the routes would not take affect until the application is restarted.
4. Maintainable would become difficult, especially among more than one developer. Do you have your database in source control?
5. You are also making the assumption that the every route is using the default MvcRouteHandler. For example if I have a "Admin" section to my site I may wish to have a "AdminRouteHandler" which would prefix "Admin" to the controller name ie. ~/admin/products/list would route to AdminProductsController and NOT ProductsController which is for the front end.
6. Unit testing of you routes will require a database or a lot of Mocking.

Please don't get me wrong, I think that the work you have done here is great, however it does not fit well in real enterprise applications.

What do you think...valid?

Roger Chapman

June 26. 2008 10:27 AM

Ken Sykora

This is a really brilliant idea, but I'm inclined to agree with Roger on the actual real world usage of something like this. It's beneficial to store these things in a database when you need to easily change them or throw a GUI on top of it for users to change them, but since the only people that need to change them are developers, it seems like these would be better off just sitting in the XML file.

Having said that, one area I could see this being awesome to be used in is something like a content management system, where you have some program that generates asp.net applications for you with boilerplate code and all the configuration/design/content is done in the GUI.

Ken Sykora

June 26. 2008 12:09 PM

Ian Suttle

@Roger/@Ken - Thank you both for your comments; all valid and appreciated. I agree in an enterprise scenario this approach has its drawbacks. The specifics of how you might want the site to work with the DB could be improved i.e. a way to reset the routes without resetting the app, using a different route handler (not sure this is valid as you're implementation changes in other ways as well), etc. I hope the provided example more explains how to not depend on compiling your routes in to your application than it does to explain it's effectiveness in a real world implementation. Thanks again guys.

Ian Suttle

July 8. 2008 07:07 AM

Net framework programmer

hello,

how i can route to main page without using MVC (We are using System.Web.Routing assembly)

Net framework programmer

Add comment


(Will show your Gravatar icon)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

July 24. 2008 07:17 AM

About Me

I'm Ian Suttle and I work for IGN Entertainment, a division of Fox Interactive Media.

Recent posts