【问题标题】:CompareAttribute and comparing against properties on a complex typeCompareAttribute 并与复杂类型的属性进行比较
【发布时间】:2011-03-08 16:30:27
【问题描述】:

我刚刚阅读了 MVC3 的新 CompareAttribute,您可以将其应用于模型的属性以定义它应该匹配的另一个属性 - 经典用例是确认电子邮件地址已正确输入,或者具有密码和 ConfirmPassword 字段。我在自己的项目中尝试实现它时遇到了问题。

我们有一个相当标准的 User 对象,除其他外,它具有以下属性:

public class User {
    ....
    [Required, RegularExpression(RegularExpressions.Email, ErrorMessage = "Please supply a valid email address")]
    public string EmailAddress

    [Required]
    public string Password
    ....
}

然后我将 User 和我们需要的其他几个对象合并到视图模型中:

public class SignUpViewModel {
   ....
   public User user { get; set; }
   ....
}

当传递到 UI 中的表单时,它允许 ModelBinder 在用户提交表单时对 User 对象以及 SignUpViewModel 中的其他对象和原始类型运行数据注释验证。当这一切“正常工作”时我真的很高兴,因为这意味着我们可以只在一个地方定义验证,而无需做太多工作来持久化到数据库或将 UI 模型映射到域模型等。

注意到 Html.EditorFor(model => model.User.Password) 发出一个名称设置为“User.Password”的值,我在 SignUpViewModel 中添加了以下内容:

[Required, Compare("User.Password")]
public string ConfirmPassword { get; set; }

但现在提交表单会触发验证错误,类似于“找不到名为 User.Password 的属性”。我希望它会遵循同样的约定,但它似乎不是:(

我真的不想将 ConfirmPassword 放入 User 对象中,因为 ConfirmPassword 纯粹是一个 UI 问题,在这样的域对象中使用它似乎是错误的。我也不想将 SignUpViewModel 中的各种对象展平,因为这开始感觉像是在定义验证规则的位置的重复,并且我们正在努力使我们的代码尽可能地保持 DRY。

有没有人遇到过一种方法来让 CompareAttribute 与兄弟对象的属性进行比较,而不是像属性所期望的那样与兄弟属性进行比较?

【问题讨论】:

    标签: asp.net-mvc-3 data-annotations


    【解决方案1】:

    删除SignUpViewModel 上的User 属性,并将User 域对象中的必要属性放在SignUpViewModel 上。

    您说您希望将您的关注点分开,并且将域对象作为视图模型上的属性是不将您的关注点分开的一个示例。

    这看起来可能会导致您编写更多代码,但请查看像 Automapper 这样的解决方案,以自动将您的域对象属性映射到视图模型属性。

    【讨论】:

    • 感谢您让我了解架构 - 您完全正确,我通过 ViewModel 将域对象传递给表单来混合关注点。
    【解决方案2】:

    尽管从架构的角度来看 smartcaveman 的响应很棒,但它并没有解决关于无法在 MVC3 中利用某些父模型(复杂模型)中包含的模型中的 CompareAttribute 客户端验证的原始问题。我知道一些可重用的 [子] 模型可以从几个父容器模型中重用,并且 CompareAttribute 在子模型中使用的情况。 MVC3 中的服务器端验证可以正常工作(当客户端禁用 javascript 时),但是 Microsoft 提供的 javascript 中有一个错误会破坏客户端验证。解决方法请点击以下链接:

    MVC3 CompareAttribute Client-side Bug (stackoverflow)

    【讨论】:

      【解决方案3】:

      我最近自己也遇到了这个问题;这是我解决它的方法。

      [Compare("OriginalPassword")]
      public string ConfirmPassword { get; set; }
      
      public string OriginalPassword
      {
          get
          {
              return User.Password;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-31
        • 1970-01-01
        • 2015-05-12
        • 1970-01-01
        • 2019-05-28
        • 2017-03-26
        相关资源
        最近更新 更多