问题 数据注释真的是验证的好主意吗?


随着我越来越多地学习ASP.NET MVC,我对数据注释的介绍越来越多。
特别是在MVC中,它们用于验证,这给了我一些关注。
最大的原因是我喜欢将我的模型保持为POCO并尽可能保持干净。
现在,如果我在解决方案中的多个项目中共享这些模型类(即Web前端,桌面应用程序,Web服务),该怎么办?
基本上我担心我的MVC前端应用程序特有的注释会影响动态数据等其他项目。 我已经将我的Business Objects与我的数据库模型(在本例中为LINQ2SQL)分开,所以我不担心注释会影响我的DAL,但我想知道我对其他项目的恐惧是否合法。

此外,我认为将所需的错误消息绑定到您的模型有点疯狂。

我想如果我为每个项目(Web,桌面,Web服务等)创建单独的模型,问题就会解决,但这实际上是我当前共享模型的直接副本。 这是正确的道路吗?
这将对我的解决方案产生重大影响(从一个模型到另一个模型的映射很多)。

你怎么看?
我想听听您认为数据注释的好坏使用。


11643
2017-09-27 21:00


起源



答案:


我发现数据注释对于规则永远不会改变的模型很方便,这取决于诸如电子邮件地址之类的上下文。

但是对于更复杂的验证(多个字段,需要DB访问等),我使用了中描述的访问者模式 访问者和扩展方法的实体验证


6
2017-09-27 23:04



我打算使用您建议的第二个选项 - 使用访客模式。我有一个问题,当模型被不同的上下文使用时,我们如何实现这一点。需要验证字符串Customer作为必填字段,但在另一个上下文中,不需要Customer。如何解决这个问题。感谢你的帮助。 - Sri Reddy
有关访问者模式的示例,请参阅此文章 lostechies.com/jimmybogard/2007/10/24/... 然后混合类似的东西 nuget.org/packages/FluentValidation - Todd Smith


答案:


我发现数据注释对于规则永远不会改变的模型很方便,这取决于诸如电子邮件地址之类的上下文。

但是对于更复杂的验证(多个字段,需要DB访问等),我使用了中描述的访问者模式 访问者和扩展方法的实体验证


6
2017-09-27 23:04



我打算使用您建议的第二个选项 - 使用访客模式。我有一个问题,当模型被不同的上下文使用时,我们如何实现这一点。需要验证字符串Customer作为必填字段,但在另一个上下文中,不需要Customer。如何解决这个问题。感谢你的帮助。 - Sri Reddy
有关访问者模式的示例,请参阅此文章 lostechies.com/jimmybogard/2007/10/24/... 然后混合类似的东西 nuget.org/packages/FluentValidation - Todd Smith


DataAnnotations不是唯一可用于验证的方法,您可以使用多种验证方法。我在使用DataAnnotations时看到的大多数验证都专门用于验证数据库中的数据。例如MaxLength()和Range()。

IValidatableObject是我在编写自己的验证时看到的最灵活的。但是,它没有帮助您使用单个存储库来保存所有对象的具体示例。但没有恐惧!

IDataErrorInfo是另一种可以验证数据的方法,这个方法可以单独用于您的MVC应用程序,它不会影响其他项目。

如果类实现了IDataErrorInfo接口,则ASP.NET MVC框架将在创建类的实例时使用此接口。因此,您可以使用服务定位器界面或类似的东西分隔您的验证。

但是,我发现IValidatableObject是一个更好的实现。


3
2017-09-27 21:34





真的,非常好的问题。特别是因为所有闪亮的演示示例应用程序都围绕DataAnnotations构建,处理所有验证,因为它是一个非常好的,闪亮的卖点。无论如何谁喜欢做验证?

我认为更好的方法是,它们应该成为更全面的验证解决方案的一部分,无论是出于您提及的结构原因还是它们的局限性 - 您如何验证诸如“此用户名是否唯一?”之类的内容。或者“该经理是否允许将此任务分配给该员工?”使用数据注释?


2
2017-09-27 21:13



我知道这是一个5岁的答案,但是你能指出我正确的方向吗?你所说的很有意义,你不能用数据注释做任何事情。 - dpp
@dpp - 是的,我已经有一段时间了,因为我构建了很多大的验证,并且在那些年里DataAnnotations有了更好的效果,而其他工具也有所改善。无论如何,我们接近它的方式是构建一个2阶段验证管道。首先是一个基于DataAnnotations的方法来检查你可以在单个对象的内存中做的事情。第二阶段是一个依赖注入的解决方案,可以将验证与数据库联系起来,查找诸如唯一性和需要查询的其他约束之类的内容。今天我可能会在这里使用FluentValidation作为粘合剂。 - Wyatt Barnett


我个人觉得DataAnnotations非常适合MVC ViewModels的验证和发布的输入。我永远不会把它们放在我的商业模式上。

我也对基于属性的验证属性非常偏爱,因为它很容易进入Reflection以发现哪些属性在哪里。


2
2017-09-27 22:55





不确定DataAnnotations是否会弄乱你的其他项目,但是除非你创建一些类来检查它们,否则它们会被忽略DataAnotations。

关于保持POCO尽可能简单,DataAnnotations的目的是将元数据和数据保持在同一位置(即,如果要求_UnitsInStock必须始终为正整数,则该要求与“库存单位”的数据定义有关“并完全符合模型的定义。它还有助于避免一些错误,因为无论你在哪里使用验证(在mvc项目中),规则总是相同的(所以当你检查时,你不能忘记检查变量中的最小值)它在页面B)。错误消息不是必需的,但您可以使用它来显示更友好的消息,并且此错误消息将随处显示。

它还可以非常轻松地实现自动服务器和客户端验证(mvc)。

另一方面,尽管您能够创建自定义属性来检查业务规则,但它需要比使用“业务类”(如果您不习惯)更多的知识和耐心,据我所知,它是仅由mvc 2正式支持。

如果您的模型类在其他项目之间共享,那么您可能还有一个共享验证层,因此请使用此验证层。如果您没有它,那么DataAnnotations将使您在MVC项目上的生活更轻松。


0
2017-09-27 22:26





我认为您不必担心在多种技术中共享装饰域。 DataAnnotations是BCL的一部分,您可以在WCF,WPF,MVC,Web窗体中使用它,您可以命名它(甚至可能在Silverlight中)。

由于DataAnnotations现在是BCL的核心部分,因此我们可以期望其他验证框架能够在将来读取这些属性,正如Enterprise Library Validation Application Block 5.0所做的那样。这允许稍后使用更复杂的验证扩展模型,而无需更改核心验证规则。

但是,我可以理解您希望将模型和验证规则分开。如果这是你想要的,验证应用程序块(VAB)可以是一个很好的选择(甚至是添加,因为它与DataAnnotations集成)。 VAB支持基于配置的验证,允许您将验证规则与模型完全分开。

但是,当您的验证规则非常简单时,VAB可能会过度。它非常强大且可扩展,但学习起来也很复杂且耗时。


0
2017-09-28 07:45



您能否提供一个或多个VAB参考的链接? - Steve
你可以先阅读 Validation instructions CS.pdf 这是EntLib动手实验室下载的一部分: bit.ly/gJpVjl (文件夹CS \ Validation \ instructions)。它很好地概述了VAB的功能。 - Steven


您的一个问题似乎是您希望保持代码清洁。 这是Asp.net MVC实现的奇妙之处。

您应该看到的是使用View模型,它有助于将您的业务逻辑与您的演示文稿分开。

这是一篇旧文章但它解释了基础知识: http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx 


0
2018-05-27 15:40