К сожалению, если механизм связывания модели тела не может проанализировать тело запроса, он замыкает запрос вместо простого пропуска привязки к параметру действия.
Если вы действительно хотите обрабатывать оба типа контента водним действием вы могли бы реализовать средство форматирования ввода для связывателя модели тела, которое обходит это поведение.Это можно сделать, притворившись, что привязка прошла успешно, если запрос имеет тип содержимого формы.
Сам форматтер прост:
/// <summary>
/// This input formatter bypasses the <see cref="BodyModelBinder"/> by returning a null result, when the request has a form content type.
/// When registered, both <see cref="FromBodyAttribute"/> and <see cref="FromFormAttribute"/> can be used in the same method.
/// </summary>
public class BypassFormDataInputFormatter : IInputFormatter
{
public bool CanRead(InputFormatterContext context)
{
return context.HttpContext.Request.HasFormContentType;
}
public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
{
return InputFormatterResult.SuccessAsync(null);
}
}
В вашем классе запуска форматировщик долженбыть добавлено:
services.AddMvc(options =>
{
options.InputFormatters.Add(new BypassFormDataInputFormatter());
});
В вашем действии вам все равно нужно будет проверить, какой из двух параметров фактически был заполнен:
[HttpPost]
public async Task<IActionResult> ExternalLogin([FromForm] ExternalLoginModel formModel, [FromBody] ExternalLoginModel bodyModel)
{
ExternalLoginModel model;
// need to check if it is actually a form content type, as formModel may be bound to an empty instance
if (Request.HasFormContentType && formModel != null)
{
model = formModel;
}
else if (bodyModel != null)
{
model = bodyModel;
}
...