为什么复杂的对象验证会像这样工作,而简单的参数却不会?

Why does complex object validation work like this, where as simple parameters do not?

在 ASP.NET 核心应用程序的控制器中,它已经用 [ApiController] 属性装饰,如果我们为需要以下对象的端点传递一个空的 JSON 对象(来自请求正文,默认情况下):

public class ComplexObject
{
    [Range(1, int.MaxValue, ErrorMessage = "Prop1 must contain a positive number.")]
    public int Prop1 { get; set; }

    [Range(1, int.MaxValue, ErrorMessage = "Prop2 must contain a positive number.")]
    public int Prop2 { get; set; }
}

验证失败,这是应该的(属性是 int 类型,它们被分配了该类型的默认值,即 0,验证检查失败。

但是,如果我们有一个端点不接受复杂对象(来自正文),而是来自 URI 的 2 个 int 变量,如果用户只是点击没有查询字符串(URI 参数)的端点,验证似乎通过了,即使在调试时两个属性都被分配了值 0。

在这种情况下使验证通过而不是不通过有什么不同?以下是我如何修饰 URI 参数的属性:

public IActionResult SomeAction([Range(1, int.MaxValue, ErrorMessage = "Prop1 must contain a positive number.")] int prop1,
            [Range(1, int.MaxValue, ErrorMessage = "Prop2 must contain a positive number.")] int prop2)
{
   ...
}

显然,如果我还添加 [Required] 属性,一切都会按预期进行。但是为什么 SomeObject 不需要 [Required] 属性就可以工作呢? [Range]基本上是一箭双雕!

public IActionResult SomeAction([Required][Range(1, int.MaxValue, ErrorMessage = "Prop1 must contain a positive number.")] int prop1,
            [Required][Range(1, int.MaxValue, ErrorMessage = "Prop2 must contain a positive number.")] int prop2)
{
   ...
}

操作参数是可选的,只有在它们存在时才会被验证。因此,如果您没有通过其中一项,则不会应用 Range 验证。当您 post 整个对象时,您就满足了第一个条件:参数具有值。因此,将对该对象进行验证,然后对它包含的所有属性进行验证。

那么,由于您的属性是不可为 null 的整数,如果您不传递值,它们将默认为零。零超出了可接受的范围,因此验证失败。它实际上并没有在这里应用必需的验证。您只是在利用默认值不被下一个验证接受的事实。