如何将正文中的 null 传递到 asp.net 核心 3.1 中的端点

How to pass null in body to endpoint within asp.net core 3.1

我在 asp.net 核心 3.1 控制器中执行以下操作

[ApiController]
[Route("example")]
public class MyExampleController : ControllerBase
{
    [HttpPost("{id}/value")]
    public async Task<IActionResult> Post(string id, [FromBody] int? value)
      => Task.FromResult(Ok());
}

如果我 post int 的主体值(例如:12 等...)

但是,我找不到获取传入的 null 值的方法。

如果我传入空主体或 null 主体,我将返回状态代码 400,并返回验证消息 A non-empty request body is required.

我还尝试将 value 参数更改为可选参数,默认值为 null:

public async Task<IActionResult> Post(string id, [FromBody] int? value = null)

如何将 null 传递给此操作?

引用Automatic HTTP 400 responses

The [ApiController] attribute makes model validation errors automatically trigger an HTTP 400 response

这将解释返回的响应。

删除 [ApiController] 以允许无效请求仍然进入控制器操作,并且如果具有该属性的附加功能对当前控制器不重要。

但是需要手动应用所需的功能

[Route("example")]
public class MyExampleController : ControllerBase {
    [HttpPost("{id}/value")]
    public async Task<IActionResult> Post(string id, [FromBody] int? value) {

        if (!ModelState.IsValid) {

            //...

            return BadRequest(ModelState);
        }

        //...

        return Ok();
    }
}

似乎与JSON的单值传递方式有关。它需要一个值,而 null 只是简单地创建一个空的请求主体。你应该考虑像这样定义一个 class

    public class MyInt{
        public int Value { get; set; }
        public bool IsNull { get; set; }
    }

    [ApiController]
    [Route("example")]
    public class MyExampleController : ControllerBase
    {
        [HttpPost("{id}/value")]
        public IActionResult Post(string id, [FromBody]MyInt value)
        {
            if(value.IsNull){

            }
            else{

            }
            return Ok();
        }
    }

换句话说,当您 POST 时,您 post 不只是使用默认值。你可以像这样用另一种方式做到这一点

[HttpPost("{id}/value")]
public IActionResult Post(string id, [FromBody]int value)...
[HttpGet("{id}/value")]
public IActionResult Get(string id)...//use the default value here

终于弄明白了,非常感谢@Nkosi 和@KirkLarkin 帮助找到了这个问题。

Startup.cs 中将控制器配置到容器中时,我们只需要将默认的 mvc 选项更改为 AllowEmptyInputInBodyModelBinding

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(x => x.AllowEmptyInputInBodyModelBinding = true);
}

这样我们就可以将 null 传递到 post 的正文中并且它工作得很好。它还通过属性应用正常模型验证,而无需手动检查 ModelState:

public async Task<IActionResult> Post(string id,
        [FromBody][Range(1, int.MaxValue, ErrorMessage = "Please enter a value bigger than 1")]
        int? value = null)