在ASP.NET Core ApiController中区分显式“ null”和“未指定”

Sto*_*-BE 5 c# model-binding asp.net-core asp.net-core-2.2

这是我潜伏在这里多年后的第一个问题,所以我希望我不会违反任何规则。

在我的某些ASP.NET Core API的POST方法中,我希望客户端可以在POST请求的正文中仅提供要更新的属性。

这是我的代码的简化版本:

[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public sealed class FooController : ControllerBase
{
    public async Task<IActionResult> UpdateFooAsync(Guid fooGuid, [FromBody]UpdateFooModel model)
    {
        ... Apply updates for specified properties, checking for authorization where needed...

        return Ok();
    }
}

public sealed class UpdateFooModel
{
    [BindProperty] public int? MaxFoo { get; set; }
    [BindProperty] public int? MaxBar { get; set; }
}

public sealed class Foo
{
    public int? MaxFoo { get; set; }
    public int? MaxBar { get; set; }
}

Run Code Online (Sandbox Code Playgroud)

MaxBar和MaxFoo都是可为空的整数值,其中null值表示没有最大值。

我正在尝试让客户端将以下内容发送到此端点:

在我的方法UpdateFooAsync中,我只想更新在请求中指定的属性。

但是,当发生模型绑定时,未指定的属性将设置为其默认值(null对于可空类型)。

找出值是显式设置为null(应设置为null)还是在请求中不存在(不应该更新)的最佳方法是什么?

我尝试检查ModelState,但是它不包含“模型”的键,仅包含Guid类型参数。

当然,任何其他解决核心问题的方法也将受到欢迎。

谢谢!

Sto*_*-BE 1

根据 @russ-w 的建议(谢谢!)在这里回答我自己的问题:通过在每个可选属性的设置器中标记 bool 属性,我们可以查明是否提供了它。

public sealed class UpdateFooModel
{
    private int? _maxFoo;
    private int? _maxBar;

    [BindProperty] 
    public int? MaxFoo
    { 
        get => _maxFoo;
        set
        {
            _maxFoo = value;
            MaxFooSet = true;
        }
    }

    public bool MaxFooSet { get; private set; }

    [BindProperty] 
    public int? MaxBar
    { 
        get => _maxBar;
        set
        {
            _maxBar = value;
            MaxBarSet = true;
        }
    }

    public bool MaxBarSet { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

当然,仍然欢迎进一步的改进或其他解决方案!