The magic of routing with multiple areas


Published: 4/5/2013, Author: Håkan Edling Categories: Programming, .NET, 0 Comments

Routing in ASP.NET MVC is pretty straight forward, however, with multiple areas and the strong possibility of having controllers with the same name in several of them strange things can happen.

In our current work with getting Piranha CMS for to play nice with MVC applications we ran into some issues with the routing and area setup. Before, when hosting the core framework in a Razor website one could be pretty sure that the manager controllers would be the only controllers around, but with a MVC application this would of course not be the case.

Our scenario was that we wanted to provide two default controllers with the template, a PageController and a PostController. However, both these names already existed in the manager area, so we ran into some issues straight away.

So how do you go about getting good separation between areas, and not clogging up the namespace availble for controllers in the default route. Let's start off by examining the route config provided when you create a new empty MVC 4 application in Visual Studio.

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }) ;

Adding a namespace to MapRoute

The first step is to add namespaces to our routes, thus making sure that only the right controllers are added to each route. In order to get this to work properly this must be added both for the default route as well as for the routes in your areas. In our template project we added the following to our default route:

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new [] { "TemplateSite.Mvc.Controllers" }) ;

After adding this we can now start the application without getting errors about having multiple controllers with the same name, but are we done? Unfortunately not.

It's seems that even though we've specified an explicit namespace for our default route it still routes all of the controllers of the other areas, however it chooses the right one in case of multiplicity. For me this is some really weird out-of-the-box behaviour after you've specified a namespace. Fortunately, weird problems tend to have weird solutions.

Just pass me that magic string

Thanks to some wicked googeling-skills of my co-worker we managed to come up with the following solution. It seems that you can pass data tokens into a route and alter its behaviour.  So by adding the following line to our default route, controllers from the other areas are no longer accessible.

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new [] { "TemplateSite.Mvc.Controllers" }
).DataTokens["UseNamespaceFallback"] = false ;

And that's it, all we needed was a magic string to get it to work. Hope that this will help you in your future quests in routing with multiple areas.


blog comments powered by Disqus