在 ASP.NET 核心模型绑定中使用 Required 和 JsonRequired 与 JSON body
Using Required and JsonRequired in ASP.NET Core Model Binding with JSON body
我正在使用 ASP.NET Core 2.0,我有一个请求 object 注释如下:
public class MyRequest
{
[Required]
public Guid Id { get; set; }
[Required]
public DateTime EndDateTimeUtc { get; set; }
[Required]
public DateTime StartDateTimeUtc { get; set; }
}
在我的控制器中:
public async Task<IActionResult> HandleRequest([FromBody] MyRequest request)
{ /* ... */ }
我注意到模型绑定的一个问题:当我发送一个包含设置为 application/json
的 header Content-Type
和一个空的 body 的请求时,如我所料,我控制器中的 request
是 null
而 ModelState.IsValid
是 false
.
但是当我有这样的 body 时:
{
"hello": "a-string-value!"
}
我的 request
不是 null
,它有所有的默认值,ModelState.IsValid
是 true
这当然是在我缺少所有 Required
属性时发生的,并且唯一存在的名字与那里的 属性 不匹配(甚至这个单个参数的类型是string
,与我的模型上的任何类型都不匹配。
所以在某种程度上,如果我的请求中没有任何内容,那些 Required
属性似乎可以工作,但如果我的请求不为空,它们就不会执行任何操作!
当我准备这个问题时,我注意到还有一个 JsonRequired
属性,它似乎处理了存在的属性。
那么,Required
和 JsonRequired
有什么区别?
为了 Required
属性的正确工作,您应该使属性可为空:
public class MyRequest
{
[Required]
public Guid? Id { get; set; }
[Required]
public DateTime? EndDateTimeUtc { get; set; }
[Required]
public DateTime? StartDateTimeUtc { get; set; }
}
现在,如果您发送缺少 Id
、EndDateTimeUtc
或 StartDateTimeUtc
的请求,相应的字段将设置为 null
,将设置为 ModelState.IsValid
false
和 ModelState
将包含错误描述,例如The EndDateTimeUtc field is required.
JsonRequired
属性特定于 JSON.Net。它在反序列化期间播放,而 Required
属性(与 System.ComponentModel.DataAnnotations
命名空间中的其他属性一样)在模型反序列化之后,在模型验证期间播放。如果 JsonRequired
属性被违反,模型将不会被反序列化,相应的动作参数将被设置为 null
.
您应该更喜欢 Required
属性而不是 JsonRequired
的主要原因是 JsonRequired
不适用于其他内容类型(如 XML)。 Required
反过来是通用的,因为它是在模型反序列化后应用的。
当您使用 [FromBody]
作为绑定源时,模型属性将获得默认值并且 [BindRequired]
将被忽略。
"Problems with Parameter Validation".
上有一个相关问题
在这种情况下,最好使用 [JsonRequired]
而不是 [BindRequired]
来强制执行绑定属性。
注意 [JsonRequired]
影响序列化和反序列化。
是的,困难在于,如果您选择 Required,Web 请求客户端的语义会发生错误更改 - 即您说您可以传入一个空值,而实际上您确实需要一个正确的值。
使用 JsonRequired 对此进行排序,但这是由 NewtonSoft 提供的,因此当您升级到 .Net Core 3 时停止工作。这是因为 .Net Core 3 使用自己的 Json 解析器而不是 NewtonSoft。
我正在使用 ASP.NET Core 2.0,我有一个请求 object 注释如下:
public class MyRequest
{
[Required]
public Guid Id { get; set; }
[Required]
public DateTime EndDateTimeUtc { get; set; }
[Required]
public DateTime StartDateTimeUtc { get; set; }
}
在我的控制器中:
public async Task<IActionResult> HandleRequest([FromBody] MyRequest request)
{ /* ... */ }
我注意到模型绑定的一个问题:当我发送一个包含设置为 application/json
的 header Content-Type
和一个空的 body 的请求时,如我所料,我控制器中的 request
是 null
而 ModelState.IsValid
是 false
.
但是当我有这样的 body 时:
{
"hello": "a-string-value!"
}
我的 request
不是 null
,它有所有的默认值,ModelState.IsValid
是 true
这当然是在我缺少所有 Required
属性时发生的,并且唯一存在的名字与那里的 属性 不匹配(甚至这个单个参数的类型是string
,与我的模型上的任何类型都不匹配。
所以在某种程度上,如果我的请求中没有任何内容,那些 Required
属性似乎可以工作,但如果我的请求不为空,它们就不会执行任何操作!
当我准备这个问题时,我注意到还有一个 JsonRequired
属性,它似乎处理了存在的属性。
那么,Required
和 JsonRequired
有什么区别?
为了 Required
属性的正确工作,您应该使属性可为空:
public class MyRequest
{
[Required]
public Guid? Id { get; set; }
[Required]
public DateTime? EndDateTimeUtc { get; set; }
[Required]
public DateTime? StartDateTimeUtc { get; set; }
}
现在,如果您发送缺少 Id
、EndDateTimeUtc
或 StartDateTimeUtc
的请求,相应的字段将设置为 null
,将设置为 ModelState.IsValid
false
和 ModelState
将包含错误描述,例如The EndDateTimeUtc field is required.
JsonRequired
属性特定于 JSON.Net。它在反序列化期间播放,而 Required
属性(与 System.ComponentModel.DataAnnotations
命名空间中的其他属性一样)在模型反序列化之后,在模型验证期间播放。如果 JsonRequired
属性被违反,模型将不会被反序列化,相应的动作参数将被设置为 null
.
您应该更喜欢 Required
属性而不是 JsonRequired
的主要原因是 JsonRequired
不适用于其他内容类型(如 XML)。 Required
反过来是通用的,因为它是在模型反序列化后应用的。
当您使用 [FromBody]
作为绑定源时,模型属性将获得默认值并且 [BindRequired]
将被忽略。
"Problems with Parameter Validation".
在这种情况下,最好使用 [JsonRequired]
而不是 [BindRequired]
来强制执行绑定属性。
注意 [JsonRequired]
影响序列化和反序列化。
是的,困难在于,如果您选择 Required,Web 请求客户端的语义会发生错误更改 - 即您说您可以传入一个空值,而实际上您确实需要一个正确的值。
使用 JsonRequired 对此进行排序,但这是由 NewtonSoft 提供的,因此当您升级到 .Net Core 3 时停止工作。这是因为 .Net Core 3 使用自己的 Json 解析器而不是 NewtonSoft。