省略“必需” JSON密钥时,验证不会在.Net Core 2.1 MVC中失败

Tre*_*yan 2 c# asp.net-core-mvc .net-core

我是.Net开发的新手,所以我认为我将从.Net Core课程开始。到目前为止,一切都很好; 我正在尝试创建一个API,该API需要在JSON对象中存在特定键。如果至少有一个键丢失,我希望它是无效的。

[HttpPost("new")]
public IActionResult CreateGPSPoint([FromBody] ModelExample dataObject)
{
   if (!ModelState.IsValid)
   {
       return BadRequest(ModelState);
   }
}
Run Code Online (Sandbox Code Playgroud)

但是,即使我省略了我发送的JSON有效负载中的某些或全部键,IsValid也会返回true。经过检查,那些缺失的键在后续模型的属性上设置为0;这就是我的模型的样子。

public class ModelExample
{
    [Required(AllowEmptyStrings = false)]
    [DisplayFormat(ConvertEmptyStringToNull = false)]
    public float Height{ get; set; }

    [Required(AllowEmptyStrings = false)]
    [DisplayFormat(ConvertEmptyStringToNull = false)]
    public decimal Width{ get; set; }

    [Required(AllowEmptyStrings = false)]
    [DisplayFormat(ConvertEmptyStringToNull = false)]
    public int Depth{ get; set; }


    //Populated by the entity later, but feel free to critique nevertheless
    public int Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

请注意,由于这种问题在这里其他地方已经提出过几次,因此我尝试了Required(AllowEmptyStrings = false)和DisplayFormat(ConvertEmptyStringToNull = false)的各种组合-我的假设是,当JSON对象出现时,将对它们进行检查被“转换(?)”为模型;但是,结果始终是相同的。

最初,我以为这可能与Automapper(我正在使用)有关,但是在任何实体/模型映射发生之前,验证都已通过。

我错过的那些特定字段也永远不会为null,因为不会将任何值设置为0(而且null仍然是有效值)。

我的想法是将数据解释为JSON对象(而不是ModelExample),并检查这些键是否早在控制器逻辑中存在(类似于Rails的“ dataObject&.dig [:key]”,但我不知道)不知道这是否可能或适当,或者是否有我错过的.Net策略。

我的问题确实是;是做错了什么,还是以上遗漏的?

如果有人能对上述工作方式有所启发,请多谢!

小智 5

初始化类属性后,它们将获得默认值

对于引用类型,这是NULL,对于结构,该值可以变化。

floatdecimalint是所有结构,并初始化为0

例如public int Depth { get; set; }将初始化为0

您发送的JSON对象没有这些属性或这些属性未定义,并且它们没有设置,这意味着0始终使用默认值。

0 存在,因此满足对“ required”的验证。

要解决此问题,请将属性类型设置为nullable

例如

[Required(AllowEmptyStrings = false)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public float? Height{ get; set; }

[Required(AllowEmptyStrings = false)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public decimal? Width{ get; set; }

[Required(AllowEmptyStrings = false)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public int? Depth{ get; set; }
Run Code Online (Sandbox Code Playgroud)

这样,当在JSON中未定义属性时,它们将获得的值,NULL并且NULL不满足“必需”的验证。

例如public int? Depth { get; set; }将初始化为NULL


另一种选择是使用BindRequiredAttribute

指示模型绑定需要属性。当应用于属性时,模型绑定系统需要该属性的值。当应用于类型时,模型绑定系统需要类型定义的所有属性的值。

例如

[BindRequired]
[Required(AllowEmptyStrings = false)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public float Height{ get; set; }

[BindRequired]
[Required(AllowEmptyStrings = false)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public decimal Width{ get; set; }

[BindRequired]
[Required(AllowEmptyStrings = false)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public int Depth{ get; set; }
Run Code Online (Sandbox Code Playgroud)

https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/validation?view=aspnetcore-2.1#notes-on-the-use-of-the-required-attribute

BindRequired属性可用于确保表单数据完整。当应用于属性时,模型绑定系统需要该属性的值。