我使用的是ASP.NET Core2.0,我有一个request对象,注释如下:
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)
{ /* ... */ }
我注意到模型绑定的一个问题:当我发送一个包含头Content-Type
设置为application/json
和一个空主体的请求时,正如我所预期的那样,我控制器中的request
是null
,而ModelState.IsValid
是false
。
但当我有了这样的身体:
{
"hello": "a-string-value!"
}
我的request
不是null
,它对所有内容都有默认值,而ModelState.IsValid
是true
当然,这是在我缺少所有Required
属性时发生的,并且唯一存在的一个属性的名称与其中的属性不匹配(甚至这个参数的类型都是string
,它与我的模型上的任何类型都不匹配)。
因此,在某种程度上,如果我的请求中没有任何内容,这些Required
属性似乎是有效的,但如果我的请求不是空的,则它们不会做任何事情!
当我准备这个问题时,我注意到还有一个JsonRequired
属性,它似乎照顾到了存在的属性。
那么,Required
和JsonRequired
有什么不同呢
发布于 2018-03-13 00:03:15
为了正确使用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
是通用的,因为它是在模型反序列化之后应用的。
发布于 2018-12-04 04:09:37
当您使用[FromBody]
作为绑定源时,模型属性将获得默认值,而[BindRequired]
将被忽略。在"Problems with Parameter Validation"上有一个相关的问题。
在这种情况下,最好使用[JsonRequired]
而不是[BindRequired]
来强制绑定属性。
请注意,[JsonRequired]
会同时影响序列化和反序列化。
发布于 2020-08-14 19:02:52
是的,困难在于如果你选择了Required,web请求的客户端的语义就会不正确地改变--也就是说,当你真的需要一个合适的值时,你可以传入一个null。
使用JsonRequired对此进行排序,但这是由NewtonSoft提供的,因此当您升级到Json Core3时将停止工作。这是因为.Net Core3使用自己的.Net解析器而不是NewtonSoft。
https://stackoverflow.com/questions/49237767
复制相似问题