ASP.NET Core Attribute routing

Willian Teleginski picture Willian Teleginski · Sep 26, 2017 · Viewed 9k times · Source

I am migrating a project to asp net core, but I could not configure these routes, i am using attributes to map actions.

Code for ASP.Net WebAPI2

[Route("api/[controller]")]
public class SalesController : Controller
{
    // api/sales/1 -> ok
    [HttpGet]
    public HttpResponseMessage Get(int id)
    {
        // Logic
    }   

    // api/sales -> ok
    [HttpGet]
    public HttpResponseMessage Get([FromUri] PaginationHelper pagination)
    {
        // Logic
    }  

    // api/sales?me -> ok
    [ActionName("Get")]
    public HttpResponseMessage GetMe(bool? me)
    {
        // Logic
    }  
}

Code for ASP.Net Core

In the file Startup.cs is set app.UseMvc();

[Route("api/[controller]")]
public class SalesController : Controller
{
    // api/sales/1 -> ok
    [HttpGet("{id}")]
    public IActionResult Get(int id)
    {
        // Logic
    }   

    // api/sales -> don't work
    [HttpGet] // -> ???
    public IActionResult Get(PaginationHelper pagination)
    {
        // Logic
    }  

    // api/sales?me -> don't work
    [HttpGet] // -> ???
    public IActionResult GetMe(bool? me)
    {
        // Logic
    }  
}

Answer

Mladen B. picture Mladen B. · Mar 1, 2019

Maybe I'm too late to this discussion, but this could be valuable to other people who end up reading this page, like I did. The problem with your API endpoints is that you configured 2 of them to handle the same route: GET /api/sales.

If you try to access that route, the framework won't be able to distinguish between Get(PaginationHelper) and GetMe(bool?). The reason why is that they both have [HttpGet] attribute, which means that both are capable of handling the route you specified in the [Route("api/[controller]")] attribute, just above your class declaration. Since those are declared as capable of handling that same route, hence your Exception (Multiple actions matched).

The solution for your problem depends on which action you want to handle that ambiguous route. Assuming that you want the route GET /api/sales to be handled by Get(PaginationHelper), you can change the GetMe(bool?) action method and its [HttpGet] attribute to something like this:

[HttpGet("me")] // GET api/sales/me
public IActionResult GetMe() {
    // Logic
}