是否应始终在模型级别强制执行验证规则?

时间:2010-02-12 15:18:25

标签: asp.net-mvc validation domain-driven-design data-annotations

使用新的ASP.NET MVC 2验证功能,我们可以使用描述有效值条件的DataAnnotations属性来修饰域模型对象的属性。 DefaultModelBinder知道这一点,并在调用控制器操作之前相应地填充ModelState.IsValid。由于验证规则是在域模型中定义的,因此将其视为模型级验证。 Scott Guthrie writes

  

在Person对象中实现规则的好处是,这将确保通过我们的应用程序中使用Person对象的任何场景强制执行验证[...]

严格来说,我认为规则并非真正强制执行,因为所有操作方法都需要检查ModelState.IsValid属性,并根据其值采取不同的行为。此外,虽然模型中的规则已定义,但它们将应用于表示层,因为这是所有模型绑定器所在的位置。但我想这只是我挑剔的选择(或者我只是错误)。

但是,在域模型级别强制执行验证规则呢?史蒂文桑德森在a post about the xVal validation framework中使用这种方法写道:

  

现在,模型层通过拒绝放置不符合所有验证和业务规则的预订来强制执行其自身的有效性。

在他的示例中,“预订管理器”(位于模型中)在使用代码尝试放置无效的预订时会引发特殊的业务规则异常。因此,消费代码无法预订无效的,无论是事先检查预订的有效性(通过ModelState.IsValid还是其他一些自定义构造)。

所以我的问题是:

假设在模型级别定义了验证规则,它们是否也应在模型中强制执行?

(请注意,我对领域驱动设计的概念很陌生,所以如果我没有使用正确的术语,请耐心等待。)

3 个答案:

答案 0 :(得分:1)

  

假设在模型级别定义了验证规则,它们是否也应该在模型中实施?

是。如果你为规则提供了一种短路的方式,那么它们就会被激活。也许不是你,也许不会很快,但未来x周/月/年的其他开发商肯定会这样做。

另外,总会出现人为错误元素 - 也许有一天,当你累了或深夜编码时,你错误地读取了这个验证标志,并且实际上是通过那些不进行验证的记录。 (别嘲笑,我自己做过!)

我现在总是确保记录无法在未经模型验证的情况下进入数据库。

答案 1 :(得分:0)

我也不太确定这个DataAnnotations。但似乎它们应该可以在任何地方工作,无论模型是否在ASP.NET MVC项目中,并且从那里使用或不使用。因为DataAnnotations是System.ComponentModel.DataAnnotations的一部分。我发现这个特别有用,因为我在VS解决方案的核心MVC项目之外的单独项目中定义了所有模型。

答案 2 :(得分:0)

DataAnnotations是ASP.NET MVC 2的一个有用功能,它确实提供了一种很好的廉价方式来获得服务器端和客户端验证。虽然,你指出一个主要的弱点是正确的。但我也不认为通过模型强制执行验证也是肯定的;我看到两个问题:

问题1:您是如何执行此操作的?您可以在构造函数和setter等上进行各种验证......但是您可以轻松地遇到需要绕过这些规则的问题。一个很好的例子是序列化;虽然你通常可以解决它,有时在对象的反序列化过程中你只需要允许对象暂时处于无效状态。另一个例子就是一个极其复杂的分层模型(例如,父母需要一个孩子而且那个孩子需要一个父母,显然你有鸡和蛋的问题,因为你不能同时构建它们。)

问题2:更高级别的验证规则(例如,用户名必须是唯一的)?您不能在模型中使用这些规则。

在一天结束时,您应该努力使您的代码尽可能干净和有意义,并保持良好的测试。我还没有看到任何基于模型的验证,它可以在100%的时间内真正完全保护数据的完整性。即使用户没有破坏您的模型,另一位开发人员最终也会这样做。