在自定义 ViewModel 中重用验证属性

2023-12-21

当我开始使用时xVal http://xval.codeplex.com/对于客户端验证,我仅实现使用域模型对象作为视图模型或视图模型中这些对象的嵌入实例的操作方法。

这种方法在大多数情况下都可以正常工作,但在某些情况下,视图需要仅显示和回发模型属性的子集(例如,当用户想要更新其密码,但不想更新其个人资料数据的其余部分时) 。

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

显然,这里的最佳实践是创建一个自定义视图模型,其中仅包含与视图相关的属性并通过填充视图模型自动映射器 http://www.codeplex.com/AutoMapper。它更干净,因为我只传输与视图相关的数据,但它远非完美,因为我必须重复域模型对象上已经存在的相同验证属性。

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

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

Thanks,

Adrian

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


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

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

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

1) 多视图模型拥有几乎相同的视图模型违反了 DRY 原则,但我觉得这种方法的成本非常低。通常,违反 DRY 会增加维护成本,但恕我直言,这样做的成本是最低的,而且金额不大。假设而言,您不会经常更改姓氏字段可以包含的最大字符数。

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

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

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

3) 疯狂的接口动态代理我尝试的最后一种技术是使用 ViewModel 的接口。最终结果是我有一个从接口继承的 User 对象,例如IAdminEdit and IUserRegistration。 IAdminEdit 和 IUserRegistration 都包含 DataAnnotation 属性,这些属性执行所有上下文特定的验证,例如带有接口的密码属性。

这需要一些技巧,而且更像是一种学术练习。 2 和 3 的问题在于 UpdateModel 和 DataAnnotationsAttribute 提供程序需要进行自定义才能了解此技术。

我最大的障碍是我不想将整个用户对象发送到视图,所以我最终使用动态代理来创建运行时实例IAdminEdit

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在自定义 ViewModel 中重用验证属性 的相关文章

随机推荐

  • 如何在不提交的情况下触发 ASP.NET 客户端验证?

    我有一个 ASP NET 网站 WebForms NOTMVC 其中有一个分为几张幻灯片的调查表 每张幻灯片都有一个下一个按钮 显然可以转换 客户端 而不是回发或远程请求 到下一张幻灯片 在每张幻灯片中 我都有几个 ASP NET 控件及其
  • 当 HTML5 音频是静态文件时,iOS 中的 HTML5 音频会显示“直播”

    对于 Windows Chrome 可能还有许多其他浏览器 此代码适用于在audio元素 param string filename return Illuminate Http Response Illuminate Contracts
  • AFNetworking 库在 iOS 7 中失败

    使用新的 iOS 7 Beta 并下载最新版本的 AFNetworking 我转到 文件 gt 将文件添加到项目 并传入目录 AFNetworking framework 现在我遇到了大量链接器错误 为了进行完整性检查 我将提交历史记录回滚
  • Python Selenium Webdriver:查找#document 元素

    我一直在使用 Python 的 Selenium Webdriver 通过此 HTML 代码获取元素 但是 我无法访问此 document 标记内的任何元素 我都用过driver find element by xpath html bod
  • Java:如何添加SSL客户端身份验证

    我有以下代码使用 SSL 连接服务器与客户端 现在我想添加客户端身份验证 我有一个服务器密钥库 JCEKS 类型 和一个客户端密钥库 JKS 类型 服务器使用信任库 cacerts 我在其中导入了两个证书 因为我也想使用此信任库进行客户端身
  • C#.NET 中的 GOTO 语句

    try block catch GOTO block finally 在这种情况下 goto 会执行吗 它不会编译 因为 GOTO block 代替 goto block 即使它是正确的 它也不会编译 因为 C 规范指出 第 8 9 3 节
  • git pull 生成“致命:未指定远程存储库。”错误

    我想开始为 Github 上托管的项目做出贡献 我已采取以下步骤 git init git拉https github com PrincetonUniversity EVCM git https github com PrincetonUn
  • 使用相同类型的静态非空指针初始化后,指向自定义类型的静态指针保持为 nullptr

    我有两个命名空间 每个命名空间都有一个指向其中一个命名空间内的类 Window 的指针 图形 h namespace Graphic class Window void init static Window window App h nam
  • Java 数组 Setter Getter

    有人可以帮我解决一个小问题吗 例如 我想为 1 名学生设置 3 个讲座 但是当我尝试此操作时 我无法设置讲座 student setStudentLecture lecture student setStudentLecture lectu
  • Android在openstreetmap上绘制路线[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在寻找一种方法来绘制路线路径openstreetmap在我的 Android 应用程序中 我只有起点和终点 但不想要一条直线 关于
  • SF 符号在 SwiftUI 中调整为相同大小看起来不正确

    我在我的应用程序中显示一排各种 SF 符号 并希望将它们的大小调整为按钮 然而 由于 SF 符号一开始的大小并不相同 当我将它们全部调整到 44x44 时 有些符号显得太大 我可以根据它们的内容来调整它们的大小 但是我实际上不知道这些符号会
  • 如何将 jquery ajax 转换为原生 javascript?

    这是我的 ajaxHandler 我想将其转换为本机 javascript 即 使用 XMLHttpRequest 但我无法理解如何转换 ajaxHandler defaultAttributes type GET url index ph
  • vue 实例和 vue 组件之间的区别?

    我是vue js新手 在学习时有一些疑问 我现在对其实例和组件之间的关系有点困惑 据我所知 vue 构建的每个应用程序都应该只有一个实例 并且只有一个实例 如果需要 它可以有任意多个组件 但最近我看到了一个演示 在该演示中它有多个实例 所以
  • org.gdal.ogr.ogrJNI.GetDriverCount() 引起的 UnsatisfiedLinkError

    我正在 Windows 7 上使用 Eclipse Luna 使用 Java 进行开发 我正在将 gdal 用于某些 ogr 进程 并且从 eclipse 运行该应用程序没问题 但在同一台计算机上从命令行运行会遇到问题 我得到以下信息 Ca
  • Google App Engine Python、virtualenv 和 mimetypes

    我有使用 djangoappengine 构建并在 App Engine 开发服务器下运行的工作项目 所以我运行 manage py runserver 并且一切正常 所有需求 django djangoappengine 等 都位于项目根
  • igraph 和 tnet 之间中心性度量的差异

    我正在尝试获取有向加权网络的中心性度量 我一直在使用igraph and tnet包在R 然而 我发现使用这两个包获得的结果存在一些差异 并且我对这些差异的原因有点困惑 见下文 require igraph require tnet set
  • Android Studio 卡在“下载组件”上

    我已经安装了 android studio 当我想下载像sdk经理等 我被困在这里 像这样 我遇到了完全相同的问题 在反复看到这些不具有描述性的下载后 我感到沮丧 此外 在高速互联网上下载也需要花费大量时间 只需等待它就会完成
  • AlertController 不在窗口层次结构中

    我刚刚使用 ViewController 类创建了一个单视图应用程序项目 我想从位于我自己的类中的函数显示 UIAlertController 这是我的带有警报的班级 class AlertController UIViewControll
  • 将 DLL 拖放到 Windows Server 2008 .net 4.0 中的 GAC(“程序集”)

    我试图将一些代码部署到客户端计算机 但我不想在客户端计算机上安装 MS Windows SDK 工具 这意味着无权访问 gacutil 我还没有为我的代码创建安装程序 看起来这可能是 net 4 0 中仅有的两个选项 在过去 我只需启动 运
  • 在自定义 ViewModel 中重用验证属性

    当我开始使用时xVal http xval codeplex com 对于客户端验证 我仅实现使用域模型对象作为视图模型或视图模型中这些对象的嵌入实例的操作方法 这种方法在大多数情况下都可以正常工作 但在某些情况下 视图需要仅显示和回发模型