5

I am integrating my project with another one

Multiple types were found that match the controller named 'XXXXX'. 
This can happen if the route that services this request ('api/{controller}/{action}/{id}') found multiple controllers defined with the same name but differing namespaces, which is not supported. 
The request for 'XXXXX' has found the following matching controllers: 
COM.example.host.XXXXXController 
COM.example.parasite.XXXXXController

Is there a way to make this somehow work with the least amount of edit from either side?

I would like to avoid having to make modifications to all of my controllers.

Thank you

herme 0
  • 686
  • 6
  • 17

2 Answers2

7

Unfortunately, that is not very simple because default controller selector (DefaultHttpControllerSelector) does not look for namespace in the full controller name when it selects controller to process request.

So, there are at least two possible solutions to your problem:

  • Write your own IHttpControllerSelector which takes controller type namespace into account. Sample can be found here.
  • Rename one of controller types to make then unique.

TL;DR Default controller selector uses the cache of controller types (HttpControllerTypeCache) which holds something like:

{
   "Customers" : [
        typeof(Foo.CustomersController),
        typeof(Bar.CustomersController)        
   ],
   "Orders" : [
       typeof(Foo.OrdersController)
   ]
}

So it uses controller name as dictionary key, but it can contain several types which have same controller name part. When request is received, controller selector gets controller name from route data. E.g. if you have default route specified "api/{controller}/{id}" then request api/customers/5 will map controller value to "customers". Controller selector then gets controller types which are registered for this name:

  • if there is 1 type, then we can instantiate it and process request
  • if there is 0 types, it throws NotFound exception
  • if there is 2 or more types, it throws AmbiguousControllerException exception (your case)

So.. definition of another named route will not help you, because you can only provide controller name there. You cannot specify namespace.

Even if you'll use Attribute Routing and specify another route for one of the controller actions

[RoutePrefix("api/customers2")]
public class CustomersController : ApiController
{
     [Route("")]
     public IHttpActionResult Get()
     //...
}

you will still face the controller selector problem because attribute routes are applied to actions - there will be no controller value in route data for those requests. Attributed routes are treated differently - they are processed as sub-routes of the "MS_attributerouteWebApi" route.

Sergey Berezovskiy
  • 215,927
  • 33
  • 392
  • 421
  • 1
    Thank you, I ended up writing a custom controller selector and make it behave like its mvc counterpart. Hopefully, sometime in the future they will provide a standard one that can handle namespaces. – herme 0 Jun 16 '17 at 20:59
-1

The easiest path for you might be to add action based routing to your web api:

RouteTable.Routes.MapRoute(
     "WithActionApi",
     "api/{controller}/{action}/{id}"
 );

To your WebApiConfig.cs, be sure to put it above the default rule. Then, change how you call your controllers by including the method name, which at this point should be or should be made unique.

RandomUs1r
  • 3,636
  • 1
  • 18
  • 38