Необязательные параметры в маршрутизации атрибутов Web Api
Я хочу обрабатывать POST из следующего API-вызова:
/v1/location/deviceid/appid
Дополнительные параметры поступают из пост-тела.
Все это отлично работает для меня. Теперь я хочу расширить свой код, разрешив "deviceid" и/или "appid" и/или BodyData быть нулевым:
/v1/location/deviceid
/v1/location/appid
/v1/location/
Эти 3 URL-адреса должны отвечать на один и тот же маршрут.
Мой первый подход (требуется BodyData):
[Route("v1/location/{deviceid}/{appid}", Name = "AddNewLocation")]
public location_fromuser Post(string deviceid = null, string appid = null, [FromBody] location_fromuser BodyData)
{
return repository.AddNewLocation(deviceid, appid, BodyData);
}
Это не работает и возвращает ошибку компиляции:
"необязательные параметры должны быть в конце"
Следующая попытка:
[Route("v1/location/{deviceid}/{appid}", Name = "AddNewLocation")]
public location_fromuser Post([FromBody] location_fromuser BodyData, string deviceid = null, string appid = null)
Теперь моя функция AddNewLocation() всегда получает BodyData=null
- даже если вызов отправляет тело.
Наконец, я устанавливаю все 3 параметра необязательно:
[Route("v1/location/{deviceid}/{appid}", Name = "AddNewLocation")]
public location_fromuser Post(string deviceid = null, string appid = null, [FromBody location_fromuser BodyData = null)
Не работайте:
Необязательный параметр BodyData
не поддерживается FormatterParameterBinding
.
Почему я хочу решение с дополнительными параметрами? Мой контроллер обрабатывает только "добавление нового местоположения" через POST.
Я хочу отправить неверные данные своим собственным исключениям или сообщениям об ошибках. Даже если в вызове отсутствуют значения. В этом случае я хочу иметь возможность принять решение об исключении или настройке значений по умолчанию моим кодом.
Ответы
Ответ 1
Для входящего запроса, такого как /v1/location/1234
, как вы можете себе представить, веб-API будет сложно автоматически определить, соответствует ли значение сегмента, соответствующее "1234", appid
, а не deviceid
.
Я думаю, вы должны изменить свой шаблон маршрута, чтобы
[Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]
, а затем проанализируйте deiveOrAppid
, чтобы выяснить тип идентификатора.
Также вам нужно сделать сегменты в шаблоне маршрута сами по себе необязательными, иначе сегменты будут считаться необходимыми. Обратите внимание на символ ?
в этом случае.
Например:
[Route("v1/location/{deviceOrAppid?}", Name = "AddNewLocation")]
Ответ 2
Другая информация. Если вы хотите использовать Ограничение маршрута, представьте, что вы хотите заставить этот параметр иметь тип int, тогда вам нужно использовать этот синтаксис:
[Route("v1/location/**{deviceOrAppid:int?}**", Name = "AddNewLocation")]
Символ ? всегда ставится перед последним символом }
Для получения дополнительной информации см. Дополнительные параметры URI и значения по умолчанию
Ответ 3
Преобразование моего комментария в ответ, чтобы дополнить @Kiran Chala ответ, поскольку он кажется полезным для аудитории -
Когда мы отмечаем параметр как необязательный в действии uri с использованием символа ?
, тогда мы должны предоставить значения по умолчанию для параметров в сигнатуре метода, как показано ниже:
MyMethod(string name = "someDefaultValue", int? Id = null)