Load ASP.Net MVC Routes dynamically at runtime from a repository
Posted by Andrew Myhre on August 2, 2008
This article was written for a preview version of ASP.Net MVC and is now out of date.
Today I read Ian Suttle’s post about loading MVC routes dynamically from a SQL database. I think it’s a cool idea, and I wanted to see if I could do the same thing with XML or a configuration file. I also wanted to introduce the factory design pattern so that people can plug in their own route repositories.
My solution comprises the following classes:
- MvcRoute – main route DTO
- MvcRouteParam – route parameter DTO
- IRouteService – interface defining a service which loads route data from a repository
- RouteServiceBase – abstract class handles most common route service operations
- ConfigRouteService – extends RouteServiceBase, is responsible for reading configuration settings and constructing an IRouteService
- DynamicRoutesConfigurationHandler and DynamicRoutesConfiguration – parse the configuration
A couple of caveats:
- It’s not complete, it’s a proof of concept
- It doesn’t handle ‘ignore’ routes
Settings your routes looks like this:
24 protected void Application_Start()
25 {
26 IRouteService routeService = new ConfigRouteService();
27 routeService.SetAppRoutes(RouteTable.Routes);
28 RegisterRoutes(RouteTable.Routes);
29 }
IRouteService is implemented thusly:
11 namespace DynamicRoutes
12 {
13 public interface IRouteService
14 {
15 List<MvcRoute> GetConfiguredRoutes();
16 RouteCollection ResetAppRoutes(RouteCollection RouteTable);
17 RouteCollection SetAppRoutes(RouteCollection RouteTable);
18 RouteCollection SetAppRoutes(RouteCollection RouteTable,
19 List<MvcRoute> ConfiguredRoutes);
20 }
21 }
Most importantly you have a method to get route data from your chosen repository (GetConfiguredRoutes) and a method to add the routes to your application RouteTable (SetAppRoutes).
The RouteServiceBase class implements all methods except GetConfiguredRoutes, and this should be the only method you need to implement yourself in order to set up a new route repository. For example, here’s the implementation for ConfigRouteService:
9 namespace DynamicRoutes
10 {
11 public class ConfigRouteService : RouteServiceBase
12 {
13 public override List<MvcRoute> GetConfiguredRoutes()
14 {
15 DynamicRoutesConfigurationSection configuration =
16 ConfigurationManager.GetSection(“dynamicRoutes”) as
17 DynamicRoutesConfigurationSection;
18
19 return configuration.Routes;
20 }
21 }
22 }
And here are the configuration handler classes:
7 namespace DynamicRoutes
8 {
9 public class DynamicRoutesConfigurationHandler : IConfigurationSectionHandler
10 {
11 public object Create(object parent, object configContext, System.Xml.XmlNode section)
12 {
13 DynamicRoutesConfigurationSection config = new DynamicRoutesConfigurationSection();
14 config.LoadRoutesFromConfig(section);
15 return config;
16 }
17 }
18 }
8 namespace DynamicRoutes
9 {
10 public class DynamicRoutesConfigurationSection : ConfigurationSection
11 {
12 public List<MvcRoute> Routes { get; set; }
13 public string TypeName { get; set; }
14 public void LoadRoutesFromConfig(XmlNode section)
15 {
16 Routes = new List<MvcRoute>();
17 TypeName = section.Attributes["type"].Value;
18 foreach (XmlNode node in section.ChildNodes)
19 {
20 if (node.Name == “route” && node.Attributes["type"].Value == “map”)
21 Routes.Add(new DynamicRouteConfiguration().LoadRouteMappingFromConfig(node));
22 }
23 }
24 }
25
26 public class DynamicRouteConfiguration
27 {
28 internal MvcRoute LoadRouteMappingFromConfig(XmlNode routeNode)
29 {
30 MvcRoute route = new MvcRoute();
31
32 route.routeName = routeNode.Attributes["name"].Value;
33 route.routePattern = routeNode.Attributes["pattern"].Value;
34 route.routeParams = new List<MvcRouteParam>();
35
36 foreach (XmlNode node in routeNode.ChildNodes)
37 {
38 if (node.Name == “param”)
39 route.routeParams.Add(LoadParamFromConfig(node));
40 }
41
42 return route;
43 }
44
45 internal MvcRouteParam LoadParamFromConfig(XmlNode paramNode)
46 {
47 MvcRouteParam param = new MvcRouteParam();
48
49 param.paramKey = paramNode.Attributes["key"].Value;
50 param.paramValue = paramNode.Attributes["defaultValue"].Value;
51
52 return param;
53 }
54 }
55 }
Finally, here’s what’s in my web.config to set up my default route:
11 <configSections>
12 <section name=“dynamicRoutes“ type=“DynamicRoutes.DynamicRoutesConfigurationHandler, DynamicRoutes“/>
13 </configSections>
14
15 <dynamicRoutes>
16 <route type=“ignore“ url=“{resource}.axd/{*pathInfo}“/>
17 <route type=“map“ name=“Default“ pattern=“{controller}/{action}/{id}“>
18 <param key=“controller“ defaultValue=“Home“/>
19 <param key=“action“ defaultValue=“Index“/>
20 </route>
21 </dynamicRoutes>
This all probably sounds like nonsense so download the complete source here.
ASP.NET MVC Archived Blog Posts, Page 1 said
[...] to VoteLoad ASP.Net MVC Routes dynamically at runtime from a repository (8/1/2008)Friday, August 01, 2008 from andrewmyhreToday I read Ian Suttle’s post about loading MVC routes [...]
Simon Hurley said
Did you manage to complete this more at all? I’m looking at building a template mvc site and didnt like the idea of specifying what could be complex rules in global.asax so I was intrigued into your solution, as i used to specify rewriting rules in the web.config in non-mvc website.
Simon Hurley said
cant seem to download your project file either. i’ve got all it anyway but cant find MvcRouteParam class.
andrewmyhre said
I’ve updated the source zip file with a much improved solution. Hope it works for you now!
Christian Weyer said
Hi,
the link to the code does not work – can you please check it?
Thanks.
andrewmyhre said
my bad – link should work now
William said
Link still does not work. wordpress complains about “Sorry, no posts matched your criteria.”
andrewmyhre said
The link in Christian’s comment was always wrong, use the link in the post.
I’ve edited Christian’s comment to remove the link.
links for 2009-05-01 « Praveen’s Blog said
[...] Load ASP.Net MVC Routes dynamically at runtime from a repository « No Free Time [...]
Cederash said
Очень было интересно читать, спасибо!