c# - 当省略 "required"JSON 键时,.Net Core 2.1 MVC 中的验证不会失败

标签 c# .net-core asp.net-core-mvc

我是 .Net 开发新手,所以我想从 .Net Core 类(class)开始。到目前为止,一切都很好;我正在尝试创建一个需要 JSON 对象中存在特定键的 API。如果至少缺少一个键,我认为它是无效的。

[HttpPost("new")]
public IActionResult CreateGPSPoint([FromBody] ModelExample dataObject)
{
   if (!ModelState.IsValid)
   {
       return BadRequest(ModelState);
   }
}
但是,即使我在发送的 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; }
}

请注意,由于此类问题已在其他地方多次提出,因此我尝试了Required(AllowEmptyStrings = false)和DisplayFormat(ConvertEmptyStringToNull = false)的各种组合 - 我的假设是,当JSON 对象被“转换(?)”为模型;然而,结果始终是一样的。

最初我认为这可能是 Automapper(我正在使用的)的问题,但验证在任何实体/模型映射发生之前就通过了。

我错过的那些特定字段也永远不会为 null,因为没有值会被设置为 0(并且 null 无论如何仍然是一个有效值)。

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

我的问题确实是;是否有什么地方做得不正确,或者上面遗漏了什么?

如果有人能够提供有关上述工作原理的启发,非常感谢!

最佳答案

当类属性初始化时,它们会得到 default value .

对于引用类型,这是NULL,对于结构,该值可能会有所不同。

floatdecimalint 都是结构体,并被初始化为相当于 0 的值。

例如public int 深度 { get;放; } 将被初始化为 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; }

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

例如公共(public)整数?深度{得到;放; } 将被初始化为 NULL

<小时/>

另一个选项是使用 BindRequiredAttribute .

Indicates that a property is required for model binding. When applied to a property, the model binding system requires a value for that property. When applied to a type, the model binding system requires values for all properties that type defines.

例如

[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; }

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

The BindRequired attribute [...] is useful to ensure form data is complete. When applied to a property, the model binding system requires a value for that property.

关于c# - 当省略 "required"JSON 键时,.Net Core 2.1 MVC 中的验证不会失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52717958/

相关文章:

c# - 获取 .NET 解决方案的完整依赖关系图

c# - 如何在 .net core/Linux 中实现 Diffie Hellman

c# - 如何将具有动态值的 javascript 对象发布到 mvc6 Controller 操作

javascript - 如何使用 javascript 和 asp.net 获取 gridview 中选中的行单元格值

c# - 为什么从我的逐字字符串中删除换行符只返回最后一行?

c# - MVC4+EntityFramework架构

c# - 我可以让我的程序集引用另一个程序集的任何版本吗?

c# - 在 EF Core Migration 中设置级联删除时,它不会在数据库中强制执行吗?

c# - 如何手动反序列化 ModelStateDictionary

c# - 方法 'UseRouting' 没有重载需要 1 个参数