2016-08-03 1 views
4

Я строю веб-API, где у меня есть один ресурс, который должен иметь 3 метода GET следующим образом:Наличие нескольких GET-методов с несколькими параметрами строки запроса в ASP.NET ядра Web Api

[HttpGet] 
    [Route("{city}/{streetName}/{streetNumber}/{littera}")] 
    public IActionResult GetByAddress([FromQuery]string city, [FromQuery]string streetName, [FromQuery]int streetNumber, [FromQuery]string littera) 
    { 
     var model = _availabilityService.FindByAddress(city, streetName, streetNumber, littera); 
     return Ok(model); 
    } 

    [HttpGet("{pointId}")] 
    public IActionResult GetByPointId(string pointId) 
    { 
     var model = _availabilityService.FindByPointId(pointId); 
     return Ok(model); 
    } 

    [HttpGet] 
    [Route("{xCoordinate}/{yCoordinate}")] 
    public IActionResult GetByCoordinates([FromQuery]decimal xCoordinate, [FromQuery]decimal yCoordinate) 
    { 
     var model = _availabilityService.FindByCoordinates(xCoordinate, yCoordinate); 
     return Ok(model); 
    } 

ГЭТ метод только с одним параметром (pointId) работает отлично, поскольку он не рассматривается как строка запроса, а скорее и id. Однако, по-видимому, остальные 2 метода не распознаются маршрутизатором в ASP.NET.

Я действительно в затруднении здесь и не могу понять, почему это не работает. То, что я смог выработать, состоит в том, что если я удалю один из методов, то другой будет работать нормально.

Любые предложения о том, что я делаю неправильно?

FYI, соответствующий URL: s должен выглядеть следующим образом:

api/1.0/availabilities?city=Metropolis&streetName=Superstreet&streetNumber=1&littera=A 

и

/api/1.0/availabilities?xCoordinate=34.3444&yCoordinate=66.3422 

спасибо!

+0

Когда вы говорите, что это не работает, что именно вы получаете, называя два других действия? 404? – jpgrassi

+0

@jpgrassi: Я получаю только 500 внутренних ошибок сервера. Я использовал отладчик, и происходит то, что конечная точка никогда не достигнута, поэтому я пришел к выводу, что моя маршрутизация запутана и запутана. :( –

ответ

9

Прежде всего вы смешиваете RouteParameters и QueryParameters.

Это:

[HttpGet] 
[Route("{xCoordinate}/{yCoordinate}")] 
public IActionResult GetByCoordinates([FromQuery]decimal xCoordinate, [FromQuery]decimal yCoordinate) 
{ 
    var model = _availabilityService.FindByCoordinates(xCoordinate, yCoordinate); 
    return Ok(model); 
} 

отображает действие контроллера GetByCoordinates в маршрут, как это:

/api/1.0/availabilities/34.3444/66.3422 

Но вы также указать, что вы ожидаете xCoordinate и yCoordinate быть связаны с параметрами запроса. Таким образом, выше url будет соответствовать действию, но xCoordinate и yCoordinate будут привязаны к его значениям по умолчанию (в данном случае 0).

Таким образом, чтобы получить желаемый маршрут, вы не должны объявлять параметры маршрута:

[HttpGet] 
[Route("")] // <- no route parameters specified 
public IActionResult GetByCoordinates([FromQuery]decimal xCoordinate, [FromQuery]decimal yCoordinate) 
{ 
    // will be matched by e.g. 
    // /api/1.0/availabilities?xCoordinate=34.3444&yCoordinate=66.3422 
} 

Теперь ваш желаемый маршрут будет соответствовать.

Примечание: Вы не можете сопоставить два действия с одним и тем же маршрутом - промежуточное ПО маршрута не будет знать, какой из них выбрать. Так же удаление параметров маршрута из GetByAddress эффективно отобразить оба действия по тому же маршруту:

/api/1.0/availabilities?{any=number&of=query&parameters=here} 

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

[HttpGet] 
[Route("address")] // <-- 
public IActionResult GetByAddress([FromQuery]string city, [FromQuery]string streetName, [FromQuery]int streetNumber, [FromQuery]string littera) 
{ 
    // will be matched by e.g. 
    // api/1.0/availabilities/address?city=Metropolis&streetName=Superstreet&streetNumber=1&littera=A 
} 

Дальнейшее чтение:

ModelBinding/Routing

Быстрый отзыв:

Набор Microsft LogLevel к Debug в appsettings.json (авто генерируется в стандартном Asp.Net Core WebApplication Template), и вы получите очень полезную информацию о выборе маршрута/ошибках при выборе маршрута на вашем консольном выходе при работе под пустельгой.

{ 
    "Logging": { 
    "IncludeScopes": false, 
    "LogLevel": { 
    "Default": "Debug", 
    "System": "Information", 
    "Microsoft": "Debug" 
} 

Или настроить регистратор отладки в StartUp.cs для LogLevel.Debug и вы получите ту же информацию в отладочный вывод непосредственно в Visual Studio.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
     // ... 

     loggerFactory.AddDebug(LogLevel.Debug); 

     // ... 
    } 
+0

Благодарим вас за хорошее объяснение. Имеет смысл то, что вы описываете. Это накладывает новый вопрос, хотя это обычный способ делать разламы, добавляя «слово маршрутизации» для ресурса, чтобы указать его значение? Спасибо за ответ, я отметил, что он ответил! :) –

+0

@ KasperP На мой взгляд, сделайте то, что лучше всего подходит для вас при разработке api. Тем не менее, особенно, когда вы спрашиваете о конвенции, REST будет такой конвенцией/парадигмой, которую вы можете (попробуйте) следовать. Я бы, вероятно, объединил «GetByAddress» и «GetByCoordinates» в одном действии поиска, поскольку, похоже, это именно так. [REST] (http://stackoverflow.com/questions/671118/what-exactly-is-restful-programming?rq=1), [URI-Design] (http://stackoverflow.com/questions/1619152/how -to-create-rest-urls-without-verbs/1619677 # 1619677) – ypsilo0n

+0

Не могу вас поблагодарить. –

Смежные вопросы