根据需要验证正文中的不可为空属性 - AspNetCore 3.1



我正在尝试验证属性/字段是否在请求中完全关闭 ModelState 无效并且 BadRequest 被发送回客户端,但是我正在努力处理请求正文中的不可空类型。

适用于可为空的类型

[Required] public string NullableString { get; set; }

适用于不可为空和可为空的参数

public IActionResult RequiredNonNullableIntQueryString([Required]int nonNullableInt)
public IActionResult RequiredNullableStringQueryString([Required]string nullableString)

但是,它不适用于请求正文中的不可为空的类型

public IActionResult RequiredNonNullableIntBody([FromBody]NonNullablesRequest request)
public class NonNullablesRequest
{
[Required] // I have also tried [BindRequired] with the same result.
public int NonNullableInt { get; set; }
}

我读过:

  • Microsoft文档 - 服务器上的模型验证 # [必需] 验证
  • 关于核心MVC中的[必需]和[绑定必需]ASP.NET 好文章

Microsoft文档指出:

.NET Core 3.0 及更高版本中的验证系统将不可为空的参数或绑定属性视为具有 [必需] 属性。十进制和整数等值类型不可为空。

很酷。。。然而后来说

在服务器上,如果属性为 null,则认为缺少所需的值。不可为空的字段始终有效,并且永远不会显示 [Required] 属性的错误消息。

为什么?这似乎真的没有意义。为什么确保所有不可为空的值都是必需的,但在未提供错误时忽略错误?

我知道许多建议表明可以执行以下方法,从而将所需参数设置为可为空。对我来说,这似乎不是一个合理的解决方案。

public class NonNullablesRequest
{
[Required]
public int? NonNullableInt { get; set; }
}

这感觉不对劲。

  • 数据类型未准确表示到达的请求的预期
  • 每次访问属性时都必须使用.HasValue.Value以避免"可能的空"警告。
  • 似乎是 C# 8.0 的可为空引用类型的反模式(C# 参考(

有没有办法将模型绑定配置为在未提供不可为空的类型时使模型状态失效?

编辑 1:

似乎存在相当多的争论: ASP.NET 核心[需要]不可为空的类型 我不确定我是否同意克里斯·帕拉特的观点。这并不是说我们期望不提供价值。事实上恰恰相反,我希望确保调用者给我价值。但是必须防御消费者没有提供足够的数据,因此系统应该拒绝400 BadRequest的请求。

由此,预期结果是int而不是int?。如果未提供任何数据,则模型绑定器应指示模型状态无效。

但是,我可以看到有两个部分的挑战 1(反序列化,然后 2( 模型绑定。

你可以为此使用两个不同的类。

一个表示您的 Web 应用程序发送到后端的内容,另一个表示您的域模型(例如实体模型(。

Http 传输对象

public class YourWebAppDto
{
[Required]
public int? NonNullableInt { get; set; }
}

域模型对象

public class YourDomainModelObject
{
public int NonNullableInt { get; set; }
}

通过分离这两个问题,可以保持域模型干净,同时解决 Web 应用程序的潜在无效输入。

当然,您需要两者之间的映射。为此,我们使用自动映射器。

我知道,这并不能直接回答你的问题,但它可能会作为一种看待事物的另一种方式有所帮助。

干杯,迈克

最新更新