Home > Programming > ASP.NET MVC Areas

ASP.NET MVC Areas

One of the new additions in ASP.NET MVC 2 was areas, which allows me to organize my projects into smaller sections. The ASP.NET MVC project that I’ve been working on has grown to a point where splitting it into smaller sections made sense. After adding areas, I noticed a few quirks.

Here I’ve created a new area called “About” with a HomeController. I’ve also added a HomeController to my root controllers folder. At this point, I’d expect to be able to visit “/Home” and “/About/Home”, each displaying their own pages. However, I received an error whenever I try to visit “/Home”.

Multiple types were found that match the controller named 'Home'. This can happen if the route that services this request ('{controller}/{action}/{id}') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.

The request for 'Home' has found the following matching controllers:
MvcDemo.Controllers.HomeController
MvcDemo.Areas.About.Controllers.HomeController

Turns out that I can’t have duplicate controller names across my areas. To remedy this issue, I needed to make an adjustment to the default route found in global.asax.cs.

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new string[] { "MvcDemo.Controllers" }  
);

Adding a fourth argument to the MapRoute method informs the handler that it should look in the specified namespace first. If it can’t find an appropriate controller in that namespace, fall back to the default behavior. After adding that, I was able to successfully visit “/Home” and “/About/Home” and hit the correct controllers.

Here I’ve created an additional controller in the About area named ContactMeController. I was able to successfully visit “/About/ContactMe” and have it display the correct page. When I visit “/ContactMe”, I expected to receive a HTTP 404 back. However, I received a different error.

The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:

~/Views/ContactMe/Index.aspx
~/Views/ContactMe/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/ContactMe/Index.cshtml
~/Views/ContactMe/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml

This indicates that the handler found a controller, but the ViewResult could not find a view. This is the same scenario we encountered above with the two HomeControllers since the handler by default does not respect area namespaces. The namespace I added earlier was a namespace that has priority, but does not constrain it to that namespace. At this point, I want the controllers in the root controllers folder to be restricted to their namespace.

Route route = routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new string[] { "MvcDemo.Controllers.*" }  
);

route.DataTokens["UseNamespaceFallback"] = false;

I’ve updated the namespace to include everything in that namespace and below. I’ve added an extra DataToken “UseNamespaceFallback” and set it to false. This extra DataToken indicates that the handler should not fall back to other namespaces in the project if it cannot find a controller in the specified namespace. Now I can visit “/ContactMe” and receive back the expected HTTP 404. At the same time, I can visit “/About/ContactMe” and have it return the correct page.

  1. cg
    April 3, 2012 at 12:24 am | #1

    Your method doesn’t seem to work. I got it working with the technique listed here http://www.philliphaydon.com/2011/07/mvc-areas-routes-order-of-routes-matter/

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: