Asp Core 3 - 如何在控制器方法中允许可为空的 [FromBody] 对象

May*_*ayo 3 c# .net-core asp.net-core asp.net-core-3.1

假设我有一个带有一个 POST 方法的简单控制器,该方法从其主体中接受一个对象。但是,此对象在 HTTP 请求正文中的存在应该是可选的。我尝试使用以下代码实现此行为

public class User
{
    public string Name { get; set; }
}

[ApiController]
[Route("[controller]")]
public class GreetingController : ControllerBase
{
    [HttpPost]
    public string SayHello([FromBody] User user = null)
    {
        return "Hello " + user?.Name;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我使用主体中的对象发出请求,则一切正常。但是使用这种配置,它无法发出空体的 POST 请求。如果我创建一个没有Content-Type标头的请求(因为实际上没有内容),我会收到以下错误:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.13",
    "title": "Unsupported Media Type",
    "status": 415,
    "traceId": "|192e45d5-4bc216316f8d3966."
}
Run Code Online (Sandbox Code Playgroud)

如果Content-Type标头具有值,application/json则响应如下所示:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
    "title": "One or more validation errors occurred.",
    "status": 400,
    "traceId": "|192e45d6-4bc216316f8d3966.",
    "errors": {
        "": [
            "A non-empty request body is required."
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,如何让请求体中的对象成为可选的呢?这是一个很常见的问题,我很好奇在 ASP Core 3 中是否有一个简单的解决方案。我不想从请求流中读取对象并自己反序列化它。

Dan*_*iel 13

现在有一种更简单的方法(自 5.0-preview7 起)

FromBodyAttribute现在,您可以通过配置名为的属性来实现每个操作方法EmptyBodyBehavior

示范:

public IActionResult Post([FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] MyModel model)
Run Code Online (Sandbox Code Playgroud)

感谢 LouraQ 的评论,它引导我找到了github 上的上述答案

  • 惊人的!但我建议让对象本身也可以为空:“MyModel?model” (3认同)

Chr*_*att 5

现在,唯一的方法是通过全局选项MvcOptions.AllowEmptyInputInBodyModelBinding. 它默认为false,因此您只需要执行以下操作:

services.AddControllers(o =>
{
    o.AllowEmptyInputInBodyModelBinding = true;
});
Run Code Online (Sandbox Code Playgroud)