验证规则是否应该始终在模型级别强制执行?
借助新的 ASP.NET MVC 2 验证功能,我们可以使用描述有效值标准的 DataAnnotations 属性来装饰域模型对象的属性。 DefaultModelBinder
了解这一点,并在调用控制器操作之前相应地填充 ModelState.IsValid
。由于验证规则是在域模型内定义的,因此这被视为模型级验证。 斯科特·格思里写道< /a>:
在我们的 Person 对象中实现规则的好处是,这将确保通过我们的应用程序中使用 Person 对象的任何场景强制执行验证 [...]
严格来说,这些规则并不是真正强制执行的 /em> 在我看来,因为所有操作方法都需要检查 ModelState.IsValid 属性,并根据其值采取不同的行动。此外,虽然规则是在模型中定义的,但它们应用在表示层中,因为这是所有模型绑定程序所在的位置。但我想这只是我对词语的选择很挑剔(或者我只是完全错误)。
但是,在域模型级别强制执行验证规则怎么样? Steven Sanderson 在 a 中使用了这种方法关于 xVal 验证框架的帖子,他写道:
现在,模型层通过拒绝进行不符合所有验证和业务规则的预订来强制执行其自身的有效性。
在他的示例中,当使用代码尝试进行无效预订时,“预订管理器”(位于模型内)会抛出特殊的业务规则异常。因此,使用代码不可能进行无效的预订,无论它是否事先检查了预订的有效性(通过ModelState.IsValid
或其他一些自定义构造) 。
所以我的问题是:
假设在模型级别定义了验证规则,是否也应该在模型中强制执行它们?
(请注意,我对领域驱动设计的概念非常陌生,因此,如果我没有使用正确的术语,请耐心等待。)
With the new ASP.NET MVC 2 validation features, we can decorate the properties of our domain model objects with DataAnnotations
attributes that describe criteria for valid values. The DefaultModelBinder
knows about this and populates ModelState.IsValid
accordingly before a controller action is invoked. Since the validation rules are defined within the domain model, this is regarded as model-level validation. Scott Guthrie writes:
The benefit of implementing the rules within our Person object is that this will ensure that the validation will be enforced via any scenario within our application that uses the Person object [...]
Strictly speaking, the rules are not really enforced in my opinion, since all the action methods need to check the ModelState.IsValid
property and act differently depending on its value. Also, although the rules are defined in the model, they are applied in the presentation layer since that's where all model binders live. But I guess this is just me being picky with the choice of words (or me just being plain wrong).
However, what about enforcing the validation rules at the domain model level? Steven Sanderson uses this approach in a post about the xVal validation framework where he writes:
Now, the model tier enforces its own validity by refusing to place bookings that don’t meet all validation and business rules.
In his example, the "booking manager" (which lives within the model) throws a special business rule exception when consuming code tries to place a booking that is invalid. Thus it is impossible for the consuming code to place an invalid booking, regardless of whether it checked the validity of the booking beforehand (through ModelState.IsValid
or some other custom construct).
So my question is:
Assuming that there are validation rules defined at the model level, should they also be enforced within the model?
(Note that I'm really new to the concept of domain-driven design, so please bear with me if I haven't used precisely the correct terminology.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(3)
DataAnnotations 是 ASP.NET MVC 2 的一个有用的功能,它确实提供了一种很好的廉价方法来获得服务器端和客户端验证。不过,你指出一个主要弱点是正确的。但我也不认为通过模型强制验证是肯定的事情;我看到两个问题:
问题 1:您如何执行此操作?您可以对构造函数和设置器等进行各种验证...,但是您很容易遇到需要规避这些规则的问题。一个很好的例子就是序列化;虽然您通常可以解决这个问题,但有时在对象的反序列化过程中,您只需要允许该对象暂时处于无效状态即可。另一个例子就是一个极其复杂的层次模型(例如,父级需要一个子级,而该子级需要一个父级,显然你有一个先有鸡还是先有蛋的问题,因为你不能同时构建它们)。
问题2:更高级别的验证规则怎么样(例如,用户名必须是唯一的)?您不能在模型中使用这些规则。
归根结底,您应该努力使代码尽可能干净并揭示意图,并保持良好的测试。我还没有看到任何基于模型的验证能够真正 100% 完全保护数据的完整性。即使用户没有破坏您的模型,其他开发人员最终也会破坏您的模型。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
是的。如果您提供一种使规则短路的方法,那么它们就会短路。也许不是你,也可能不是很快,但肯定是其他开发人员在未来的 x 周/月/年内完成的。
另外,总是存在人为错误因素 - 也许有一天,当您感到疲倦或在深夜编码时,您错误地读取了此验证标志,并且实际上让记录通过了不验证的记录。 (不要嘲笑,我自己已经做到了!)
我现在总是确保记录在未经模型验证的情况下无法进入数据库。
Yes. If you provide a way for the rules to be short-circuited, then they will be. Maybe not by you, and maybe no time soon, but surely by other developers in x weeks/months/years in the future.
Plus there's always the human error element - maybe one day when you're tired or coding late at night, you incorrectly read this validation flag and are actually letting records through that don't validate. (Don't scoff, I've done it myself!)
I now always make sure a record cannot get through to the database without being validated by the model.