我有一个API操作,我希望它接受表单数据或原始JSON。
这是我的职能
[HttpPost]
public async Task<IActionResult> ExternalLogin([FromForm]ExternalLoginModel formModel, [FromBody]ExternalLoginModel bodyModel)
{
所以我希望他们能够以两种不同的方式发送相同的数据,当我尝试使用form-data方法时,出现415错误。当我尝试使用原始JSON时,效果很好。
我希望能够将其保留在一个功能中,但是如果我必须将其分解为两个,就可以。
答案 0 :(得分:1)
不幸的是,如果主体模型绑定程序无法解析请求主体,它将短路请求,而不是简单地跳过与action参数的绑定。
如果您确实想在一个动作中处理两种内容类型,则可以为主体模型绑定程序实现输入格式化程序,从而绕过此行为。如果请求具有表单内容类型,它可以通过假装绑定成功完成。
格式化程序本身很简单:
/// <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;
}
...