asp.net-mvc - 在自定义 ViewModel 中重用验证属性

标签 asp.net-mvc validation architecture automapper xval

当我开始使用 xVal对于客户端验证,我只实现了将域模型对象用作 View 模型或 View 模型中这些对象的嵌入实例的操作方法。

这种方法在大多数情况下都可以正常工作,但是在某些情况下, View 只需要显示和回发模型属性的子集(例如,当用户想要更新他的密码,而不是他的其余配置文件数据时) .

一个(丑陋的)解决方法是在表单上为表单上不存在的每个属性设置一个隐藏的输入字段。

显然这里的最佳实践是创建一个自定义 View 模型,它只包含与 View 相关的属性,并通过 Automapper 填充 View 模型。 .因为我只传输与 View 相关的数据,所以它更干净,但它远非完美,因为我必须重复域模型对象上已经存在的相同验证属性。

理想情况下,我想通过 MetaData 属性将域模型对象指定为元类(这通常也称为“伙伴类”),但这不起作用,因为当元数据类具有以下属性时 xVal 抛出不存在于 View 模型上。

有什么优雅的解决方法吗?我一直在考虑破解 xVal 源代码,但也许到目前为止我还忽略了其他一些方法。

谢谢,

阿德里安

编辑:随着 ASP.NET MVC 2 的到来,这不再只是一个与验证属性相关的问题,它也适用于编辑器和显示属性。

最佳答案

这就是为什么您的输入屏幕不应该与您的模型紧密耦合的典型原因。这个问题实际上每月会在 MVC 标签上弹出 3-4 次。如果我能找到上一个问题并且这里的一些评论讨论很有趣,我会欺骗。 ;)

您遇到的问题是您试图将模型的两个不同验证上下文强制转换为在大量场景下失败的单个模型。最好的例子是注册一个新用户,然后让管理员稍后编辑用户字段。您需要在注册期间验证用户对象的密码,但您不会向编辑用户详细信息的管理员显示密码字段。

绕过这些的选择都是次优的。我现在已经为 3 个项目解决了这个问题,并且实现以下解决方案从来都不是干净的,而且通常令人沮丧。我要努力成为 实用忘记所有其他人正在进行的 DDD/db/model/hotnessofthemonth 讨论。

1) 多 View 模型
拥有几乎相同的 View 模型违反了 DRY 原则,但我觉得这种方法的成本非常低。通常违反 DRY 会增加维护成本,但恕我直言,这方面的成本是最低的,而且并不多。假设您不会经常更改 LastName 字段的最大字符数。

2) 动态元数据
MVC 2 中有用于为模型提供您自己的元数据的钩子(Hook)。使用这种方法,您可以根据当前 HTTPRequest 以及因此 Action 和 Controller 来提供用于提供元数据的任何内容来排除某些字段。我已经使用这种技术构建了一个数据库驱动的权限系统,该系统进入数据库并告诉 DataAnnotationsMetadataProvider 的子类排除存储在数据库中的基于属性的值。

这种技术在 atm 上运行良好,但唯一的问题是使用 UpdateModel() 进行验证.为了解决这个问题,我们创建了 SmartUpdateModel()该方法也进入数据库并自动生成排除字符串 [] 数组,以便不验证任何不允许的字段。我们当然出于性能原因缓存了它,所以它还不错。

只是想重申一下,我们在模型上使用了 [ValidationAttributes],然后在运行时用新规则取代了它们。最终结果是 [Required]如果用户没有访问权限,则不会验证 User.LastName 字段。

3) 疯狂界面动态代理的东西
我尝试的最后一种技术是使用 ViewModel 的接口(interface)。最终结果是我有一个继承自 IAdminEdit 等接口(interface)的用户对象。和 IUserRegistration . IAdminEdit 和 IUserRegistration 都将包含 DataAnnotation 属性,这些属性执行所有特定于上下文的验证,例如带有接口(interface)的 Password 属性。

这需要一些技巧,并且比其他任何事情都更像是一种学术练习。 2 和 3 的问题是需要自定义 UpdateModel 和 DataAnnotationsAttribute 提供程序以了解此技术。

我最大的绊脚石是我不想将整个用户对象发送到 View ,所以我最终使用动态代理来创建 IAdminEdit 的运行时实例。

现在我明白这是一个非常特定于 xVal 的问题,但是像这样的动态验证的所有道路都会导致内部 MVC 元数据提供程序的定制。由于所有元数据的东西都是新的,在这一点上没有什么是干净或简单的。自定义 MVC 的验证行为所要做的工作并不难,但需要深入了解所有内部结构的工作原理。

关于asp.net-mvc - 在自定义 ViewModel 中重用验证属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2059932/

相关文章:

c# - 不知道这样的主机,ClientDependency

JQuery 和验证插件

architecture - AWS 可扩展架构设计

c# - ASP.NET MVC - 正确使用 View 模型和命令模式

asp.net - OWIN 如何 Hook ASP.NET 启动

c# - 检测 HTML 字符串是否包含 C# 中的可见文本

javascript - 如何验证输入的*前*两个字符是字母?

c++ - 接受并识别任何类型的输入 C++

.net - WPF、Windows 窗体还是其他?

architecture - 基于重用的软件工程和基于组件的软件工程之间的区别?