Синтаксический сахар в Web Api - как его опустить [FromBody]
Можно ли опустить запись [FromBody]
?
[HttpPost]
public string SomeMethod([FromBody]SomeModel model)
{
return "OK";
}
Должен ли я применить какой-то глобальный атрибут? Как этого добиться?
2 ответа
Атрибуты привязки модели в MVC 5 задают " BindingSource
"для каждого параметра в действии и может также указывать для каждого свойства в контроллере. Вы можете видеть конкретно код, в котором он выбирает его для FromBody
атрибут в BodyModelBinder
Позвольте мне сначала сказать, что вы должны остерегаться этого, начиная с бета6 (и я думаю, что в бета5 есть какой-то момент), имея несколько параметров / свойств с BindingSource.Body
запрещено, и вы не сможете использовать свои действия, если у вас есть несколько параметров, оставленных по умолчанию. Это может быть на самом деле желательно, если вы хотите больше аннотировать; я думаю, что вы этого не делаете.
Вы можете увидеть в DefaultApiDescriptionProvider
где установлен источник по умолчанию; к сожалению, на этом этапе нет никакой зацепки, и сам метод является частным, а не виртуальным; вам нужно будет заново реализовать весь класс.
Как только вы это сделаете, зарегистрировать его в ConfigureServices
использовать вместо этого:
services.TryAdd(ServiceDescriptor.Transient<IApiDescriptionProvider, YourApiDescriptionProvider>());
Вы также можете видеть, что по умолчанию регистрируется в источнике.
Вероятно, есть несколько способов добиться этого.. вот один из способов: пользовательский ActionValueBinder..
Напишите собственный класс для расширения из
DefaultActionValueBinder
,открытый класс FromBodyParameterBindingActionValueBinder: DefaultActionValueBinder
Переопределите метод GetParameterBinding.
protected override HttpParameterBinding GetParameterBinding(HttpParameterDescriptor parameter) { return parameter.ActionDescriptor.SupportedHttpMethods.Contains(HttpMethod.Post) || parameter.ActionDescriptor.SupportedHttpMethods.Contains(HttpMethod.Put) ? parameter.BindWithAttribute(new FromBodyAttribute()) : base.GetParameterBinding(parameter); }
По сути, мы говорим, что если система Web API получает вызов POST или PUT, в качестве методологии привязки параметров по умолчанию используется FromBody.
Как только мы получим наш пользовательский переплет, зарегистрируйте его глобально.
GlobalConfiguration.Services.Replace (typeof (IActionValueBinder), новый FromBodyParameterBindingActionValueBinder());
это значит, что для каждого запроса POST/PUT Web API будет пытаться создать модель из тела запроса. вам не нужно предоставлять [FromBody]
атрибут явно.
Сказав это, вы должны понимать последствия того, что вы запрашиваете..
Веб-API имеет некоторые правила по умолчанию для привязки модели. (может быть изменено)
- параметры действия примитива сначала, посмотрел в строку запроса
- тогда запросите тело.
- Параметры комплексного действия сначала рассматриваются в теле запроса.
- затем строка запроса.
также веб-интерфейс может читать только первый [FromBody]
параметр действия.. последующие параметры не могут быть прочитаны из тела.
причина, по которой я перечисляю вышеупомянутые правила, заключается в том, что вы знаете о поведении, когда ожидаете, что какая-то модель будет создана, но веб-API, похоже, не создает ее из тела.
для меня, явно предоставляя [FromBody]
гораздо более читабельно и предсказуемо... но если вы полностью контролируете свои API с точки зрения глаголов Http и ожидаете, что все запросы будут проходить через Body, это вполне допустимо.