Confused with FromBody в ядре ASP.NET

У меня есть следующий метод WEB API и есть шаблон SPA с угловым:

[HttpPost]
public IActionResult Post([FromBody]MyViewModel model)

Я думал, что на основе этой темы нет необходимости использовать [FromBody] здесь, так как я хочу прочитать значение из тела сообщения, поэтому нет необходимости переопределять поведение по умолчанию, но если я не использую [FromBody], модель, которая поступает из Angular, равна нулю. Я действительно смущен, почему я должен использовать [FromBody], так как я использовал поведение по умолчанию?

Ответы

Ответ 1

Вопрос, на который вы ссылаетесь, ссылается на web-api. Вы используете core-mvc, который был переписан для объединения конвейеров для предыдущих версий mvc и web-api в один класс Controller.

При публикации json (как указано в x-www-form-urlencoded) атрибут [FromBody] требуется, чтобы инструктировать ModelBinder использовать заголовок типа контента, чтобы определить, IInputFormatter используется для чтения запроса.

Подробное объяснение привязки модели к json в core-mvc см. В статье привязки модели JSON POST в ASP.NET Core.

Ответ 2

А здесь альтернативный подход, предполагающий, что вам нужно поддерживать [FromForm] и [FromBody] в вашем Controller API…

Front-End (угловой код):

forgotPassword(forgotPassword: ForgotPassword): Observable<number> {
  const params = new URLSearchParams();
  Object.keys(forgotPassword).forEach(key => params.append(key, forgotPassword[key]));
  return this.httpClient.post('${this.apiAuthUrl}/account/forgotpassword', params.toString(), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } });
}

Back-End (код С#):

[AllowAnonymous]
[HttpPost("[action]")]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model) { }

Теперь ваша подпись может остаться прежней, чтобы она могла поддерживать оба.

И еще один более постоянный подход, о котором я подумал, обращаясь.

https://benfoster.io/blog/aspnet-core-customising-model-binding-conventions.

Надеюсь, это поможет кому-то!

Ответ 3

Для тех, кто видит эту проблему .net core 3 - вам нужно добавить [ApiController] в контроллер, где вы расширяете ControllerBase. [FromBody] необходим, только если вы работаете с контроллером MVC.

Это приводит к тому, что тело автоматически обрабатывается так, как вы ожидаете.

Документация Microsoft для атрибута ApiController