2
votes

Problem

For the default route MVC is returning a "Multiple types were found that match the controller named 'admin'." error instead of a 404 not found. There is no admin controller in that namespace.

We're using MVC 5.2.2.

Background

We're using MVC areas. Two areas contain an "admin" controller. When you use the full path as defined in their respective routes, both areas' admin controllers are accessible and work correctly.

The problem arises when you try to access "admin" from the default route. Admin does not exist in that context, so we'd expect a 404 not found, however instead we receive:

 Multiple types were found that match the controller named 'admin'. 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 'admin' has found the following matching controllers:
  DMP.Stock.Web.Controllers.AdminController
  DMP.Inventory.Web.Controllers.AdminController 

Here is our default route and two area routes:

 public static void RegisterRoutes(RouteCollection routes)
 {
   // Default Route
   routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    namespaces: new string[] { "DMP.Core.Web.Controllers" }
    );
 }

 public override void RegisterArea(AreaRegistrationContext context)
 {
   // Area 1: Stock
   context.MapRoute(
    name: "Stock_default",
    url: "Stock/{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    namespaces: new string[] { "DMP.Stock.Web.Controllers" }
     );
 }

 public override void RegisterArea(AreaRegistrationContext context)
 {
  // Area 2: Inventory 
  context.MapRoute(
   "Inventory_default",
   "Inventory/{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    namespaces: new string[] { "DMP.Inventory.Web.Controllers" }
     );
 }

/Stock/Admin/Index works correctly.

/Inventory/Admin/Index works correctly.

/Admin/ does not work correctly (expect: 404 not found, receive "multiple controllers" error).

The errors suggests we add namespaces to our routes, but as you can see above both the default and the two areas already have a namespace definition. The default route points at a namespace without any "admin" controllers in it.

I think MVC is trying to be "helpful" by searching for possible controllers that could match the requested URL. Is there any way I can turn that off?

1
I think ASP.NET MVC can't recognize which /Admin to load, because there are two /Admin views?Burak Karakuş
It shouldn't be trying to load anything at all, as there is no admin controller defined in the default's DMP.Core.Web.Controllers namespace.Safari Jones

1 Answers

5
votes

I've been able to resolve this issue myself. Here is the solution I found:

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

Note the addition of .DataTokens["UseNamespaceFallback"] = false; this is what resolves the issue. There isn't very much (any?) documentation on this functionality, however I found it while reading the MVC source code, specifically within DefaultControllerfactory (the source of this issue).

After you know to google for "UseNamespaceFallback" you can find a few blog posts and questions where people have had a similar issue and resolved it the same way. However I can find no MSDN documentation on this DataToken.