Маршрутизация Web API с несколькими параметрами

Я пытаюсь выяснить, как сделать маршрутизацию для следующих веб-API контроллера:

public class MyController : ApiController
{
    // POST api/MyController/GetAllRows/userName/tableName
    [HttpPost]
    public List<MyRows> GetAllRows(string userName, string tableName)
    {
        ...
    }

    // POST api/MyController/GetRowsOfType/userName/tableName/rowType
    [HttpPost]
    public List<MyRows> GetRowsOfType(string userName, string tableName, string rowType)
    {
        ...
    }
}

на данный момент я использую этот маршрут для URLs:

routes.MapHttpRoute("AllRows", "api/{controller}/{action}/{userName}/{tableName}",
                    new
                    {
                        userName= UrlParameter.Optional,
                        tableName = UrlParameter.Optional
                    });

routes.MapHttpRoute("RowsByType", "api/{controller}/{action}/{userName}/{tableName}/{rowType}",
                    new
                    {
                        userName= UrlParameter.Optional,
                        tableName = UrlParameter.Optional,
                        rowType= UrlParameter.Optional
                    });

но на данный момент работает только первый метод (с 2 параметрами). Я на правильных линиях, или я получил формат URL или маршрутизацию совершенно неправильно? Маршрутизация кажется мне черной магией...

2 ответов


проблема в вашем api/MyController/GetRowsOfType/userName/tableName/rowType URL всегда будет соответствовать первому маршруту, поэтому второй никогда не достигается.

простое исправление, зарегистрируйте свой RowsByType путь первый.


Я видел WebApiConfig get"из-под контроля" С сотни маршрутов помещен в нем.

вместо этого я лично предпочитаю Маршрут

Вы путаете его с POST и GET

[HttpPost]
public List<MyRows> GetAllRows(string userName, string tableName)
{
   ...
}

протоколы HttpPost и GetAllRows ?

почему бы вместо этого не сделать это:

[Route("GetAllRows/{user}/{table}")]
public List<MyRows> GetAllRows(string userName, string tableName)
{
   ...
}

или измените на маршрут ("PostAllRows" и PostRows я думаю, что вы действительно делаете запрос GET, поэтому код, который я показываю, должен работать для вас. Ваш вызов от клиента будет тем , что находится в маршруте, поэтому он найдет ваш метод с GetAllRows , но сам метод, это имя может быть любым, что вы хотите, так что пока вызывающий абонент соответствует URL-адресу в маршруте, вы можете поместить GetMyStuff для метода, если вы действительно хотите.

обновление:

Я на самом деле предпочитаю быть explicit С типом HTTP methods И я предпочитаю сопоставлять параметры маршрута с методом params

[HttpPost]
[Route("api/lead/{vendorNumber}/{recordLocator}")]
public IHttpActionResult GetLead(string vendorNumber, string recordLocator)
{ .... }

(маршрут lead не нужно соответствовать имени метода GetLead но вы захотите сохранить те же имена на парах маршрута и парамах метода, даже если вы можете изменить порядок , например, поставить recordLocator перед vendorNumber, даже если маршрут противоположен - я этого не делаю, так как зачем делать его более запутанным).

бонус: Теперь ты всегда можно использовать regex в маршрутах, например

[Route("api/utilities/{vendorId:int}/{utilityType:regex(^(?i)(Gas)|(Electric)$)}/{accountType:regex(^(?i)(Residential)|(Business)$)}")]
public IHttpActionResult GetUtilityList(int vendorId, string utilityType, string accountType)
    {