c# - .Net Core API Controller 接受表单或正文数据

标签 c# api asp.net-core

我有一个 API 操作,我希望它接受表单数据或原始 JSON。

这是我的功能

    [HttpPost]
    public async Task<IActionResult> ExternalLogin([FromForm]ExternalLoginModel formModel, [FromBody]ExternalLoginModel bodyModel)
    {

所以我希望他们能够以两种不同的方式发送相同的数据,当我用表单数据尝试这种方法时,我得到了 415 错误。当我尝试使用原始 JSON 时,它工作正常。

我希望能够将它保留在一个函数中,但如果我必须将它分成两个,那就这样吧。

最佳答案

不幸的是,如果主体模型绑定(bind)器无法解析请求主体,它会将请求短路,而不是简单地跳过对操作参数的绑定(bind)。

如果您真的想在一个操作中处理这两种内容类型,您可以为绕过此行为的 body 模型 Binder 实现一个输入格式化程序。如果请求具有表单内容类型,它可以通过假装绑定(bind)成功来实现。

格式化程序本身很简单:

/// <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;
    }

    ...

关于c# - .Net Core API Controller 接受表单或正文数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54886644/

相关文章:

c# - NavigationManager - 获取 Blazor 组件中的当前 URL

c# - 将字符串格式化为日期

java - 使用 Jax-Rs 在 RestApi 调用上返回用户定义的类对象时出错

swift - 如何在 Swift 3 中发出 GET 请求?

api - AngularJS Protractor E2E 模拟

asp.net-core - 从 Angular 5 注销 MVC 应用程序

c# - 行执行后更新值(类似于var++)

c# - AutoMockContainer 支持具有非接口(interface)依赖性的自动模拟类

c# - .Net MySql 错误 "The given key was not present in the dictionary"

c# - Asp.Net Core Web Api 中端点之间的内存缓存似乎有所不同