Синтаксический сахар в 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..

  1. Напишите собственный класс для расширения из DefaultActionValueBinder,

    открытый класс FromBodyParameterBindingActionValueBinder: DefaultActionValueBinder

  2. Переопределите метод 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.

  1. Как только мы получим наш пользовательский переплет, зарегистрируйте его глобально.

    GlobalConfiguration.Services.Replace (typeof (IActionValueBinder), новый FromBodyParameterBindingActionValueBinder());

это значит, что для каждого запроса POST/PUT Web API будет пытаться создать модель из тела запроса. вам не нужно предоставлять [FromBody] атрибут явно.


Сказав это, вы должны понимать последствия того, что вы запрашиваете..

Веб-API имеет некоторые правила по умолчанию для привязки модели. (может быть изменено)

  1. параметры действия примитива сначала, посмотрел в строку запроса
  2. тогда запросите тело.
  3. Параметры комплексного действия сначала рассматриваются в теле запроса.
  4. затем строка запроса.

также веб-интерфейс может читать только первый [FromBody] параметр действия.. последующие параметры не могут быть прочитаны из тела.

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

для меня, явно предоставляя [FromBody] гораздо более читабельно и предсказуемо... но если вы полностью контролируете свои API с точки зрения глаголов Http и ожидаете, что все запросы будут проходить через Body, это вполне допустимо.

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