Маршрутизация основных атрибутов ASP.NET

Я переносил проект в ядро ​​asp net, но я не смог настроить эти маршруты, я использую атрибуты для сопоставления действий.

Код для 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
    }  
}

Код для ASP.Net Core

В файле Startup.cs установлено 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
    }  
}

1 ответ

Может быть, я слишком опоздал к этой дискуссии, но это может быть полезно для других людей, которые в конечном итоге читают эту страницу, как я. Проблема с вашими конечными точками API состоит в том, что вы настроили 2 из них для обработки одного и того же маршрута: GET /api/sales,

Если вы попытаетесь получить доступ к этому маршруту, фреймворк не сможет различить Get(PaginationHelper) а также GetMe(bool?), Причина в том, что они оба имеют [HttpGet] атрибут, который означает, что оба способны обрабатывать маршрут, который вы указали в [Route("api/[controller]")] атрибут, чуть выше вашего объявления класса. Поскольку они объявлены способными обрабатывать тот же маршрут, следовательно, ваше исключение (Multiple actions matched).

Решение вашей проблемы зависит от того, какое действие вы хотите обработать по этому неоднозначному маршруту. Предполагая, что вы хотите маршрут GET /api/sales быть обработанным Get(PaginationHelper), вы можете изменить GetMe(bool?) метод действия и его [HttpGet] приписать что-то вроде этого:

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

Новая структура ожидает более явного указания намерения конечной точки.

[Route("api/[controller]")]
public class SalesController : Controller {

    [HttpGet("{id:int}")] // GET api/sales/1
    public IActionResult Get(int id) {
        // Logic
    }

    [HttpGet] // GET api/sales?page=1 assuming PaginationHelper has page property
    public IActionResult Get([FromQuery]PaginationHelper pagination) {
        // Logic
    } 

    [HttpGet] // GET api/sales?me=true
    public IActionResult GetMe(bool? me = false) {
        // Logic
    }  
}

Справочное ядро Asp.Net: привязка модели

Другие вопросы по тегам