0

We're using specific route attributes for all our web api routes.

We want to split up a controller class, so we're moving some update functions out to a separate controller class. We've subsequently got an odd situation with routing.

The original controller class looked like this:

[RoutePrefix("activities")]
public class ActivitiesController : ApiController
{
    ... 
    [Route("{activityId:int:min(1)}"), HttpPut]
    public void Put(int activityId, [FromBody] NewActivity value) {}

    [Route("{activityId:int:min(1)}"), HttpGet]
    public dynamic Get(int activityId) {}   
    ...
}

And we then split out the updates, so we end up with this:

[RoutePrefix("activities")]
public class ActivitiesUpdateController : ApiController
{
    ...
    [Route("{activityId:int:min(1)}"), HttpPut]
    public void Put(int activityId, [FromBody] NewActivity value) {}

    ...
}


[RoutePrefix("activities")]
public class ActivitiesController : ApiController
{
    ...
    [Route("{activityId:int:min(1)}"), HttpGet]
    public dynamic Get(int activityId) {}
    ...
}

If we then try to call either endpoint: - PUT activities/42 - GET activities/42

We get the error:

Multiple controller types were found that match the URL. This can happen if attribute routes on multiple controllers match the requested URL.

The request has found the following matching controller types: 
API.Controllers.ActivitiesUpdateController
API.Controllers.ActivitiesController

If both endpoints are in the same class (either the new one or the old), everything works correctly. Different classes raises the error.

If I dump out the endpoints using ApiExplorer, both end points are where they should be and are not repeated in the other class, so there's no obvious duplication.

I've tried renaming functions, explicit routes (i.e. ~/activities/:id), adding HttpGet & HttpPut doesn't seem to make a difference.

Is this some weird "feature" where the same endpoint with different methods have to be in the same class?

It makes no sense.

Reece
  • 1
  • 1
  • Non-sensical because the error is confusing; most people see the route and method as being unique, i.e. GET activities/:id is different from PUT activities/:id. It's using just the route to locate the controller and ignoring the method, which doesn't make sense when you're used to Put(int id) being a different C# function from Get(int id). If you want to fully qualify the route, you have to do it for every route that matches, which is a bit of a pain when there's a lot of them and an easy thing to forget if adding new endpoints. We want it split for injection and testability purposes. – Reece Sep 18 '19 at 05:28
  • Anyhow, all good, got a solution now. – Reece Sep 18 '19 at 05:31

1 Answers1

0

Not to worry, I came across this after I posted - don't know how I missed it before:

Multiple controllers with same URL routes but different HTTP methods

Reece
  • 1
  • 1