【问题标题】:Property-level validation errors hinder the validation of Class-level validation属性级验证错误阻碍了类级验证的验证
【发布时间】:2010-06-23 06:36:06
【问题描述】:

授予赏金后更新

一个新的解决方案正在解决这个问题。请参考此处的 ASP.NET MVC 3 Preview 1:http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx

查看模型验证改进部分,您将在其中看到我的问题的解决方案。


原帖

参考我之前的帖子 How to validate two properties with ASP.NET MVC 2,我在其中询问如何比较两个属性以进行模型验证。

我确实发现答案很有用,但我遇到了一个完全不同的问题:

问题:如果 Property-level ValidationAttribute 包含错误,则 Class-level ValidationAttributes 不会被验证。

请考虑以下几点:

[EqualTo("Email", "EmailConfirm", ErrorMessage = "E-mailadresserne skal være ens")]
[EqualTo("Password", "PasswordConfirm", ErrorMessage = "Adgangskoderne skal være ens")]
[Bind(Exclude="UserId")]
public class EditSiteUser
{
    [Required(ErrorMessage="Du skal bekræfte adgangskode")]
    public string PasswordConfirm { get; set; }

    [Required(ErrorMessage="Du skal bekræfte e-mailadressen")]
    [Email(ErrorMessage="Ugyldig e-mailadresse")]
    public string EmailConfirm { get; set; }
    public int UserId { get; set; }

    [Required(ErrorMessage = "Du skal indtaste et brugernavn")]
    public string Username { get; set; }

    [Required(ErrorMessage = "Du skal indtaste en adgangskode")]
    public string Password { get; set; }

    [Required(ErrorMessage = "Du skal indtaste en e-mailadresse")]
    [Email(ErrorMessage = "Ugyldig e-mailadresse")]
    public string Email { get; set; }
}

这里我有两个类级别的属性来验证 EmailConfirm 和 PasswordConfirm。

如果像用户名这样的字段为空,因此产生错误,则永远不会验证两个 EqualTo 属性。

有没有人有解决这个问题的建议?

编辑:如果您需要有关此问题的更多信息,请在 cmets 中询问,我很乐意为您提供所需的任何其他信息。

问题:

问:“如果属性级检查失败,为什么类级检查得到验证很重要?”。

答:“因为这是表单的一部分,用户在表单中输入信息,然后通过 AJAX 发回。当表单返回时,它应该显示所有当前问题。”

问:“您在类中放置的 EqualTo 属性到底是什么?它是自定义验证属性吗?如果是,它是如何工作的?它有什么作用?”

答:EqualTo 是一个类级别的 ValidationAttribute,它比较类实例的两个属性的值。查找“PropertiesMustMatchAttribute”以获得类似的实现。

【问题讨论】:

  • 如果属性级检查失败,为什么类级检查得到验证很重要?
  • 我将根据您的问题编辑帖子,并在下面提供答案。 :-)
  • 好的,下一个问题。您在类中放置的 EqualTo 属性到底是什么?它是自定义验证属性吗?如果是这样,它是如何工作的?它有什么作用?

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


【解决方案1】:

这不受支持。如果任何属性级别验证失败,则不执行类级别验证。我建议你看看MVC Foolproof Validation。它扩展了 MVC 验证以添加对条件属性验证的支持。我认为这将解决这个特殊情况的问题。

项目网站声明它不适用于 MVC2 RC,因此您必须下载源代码并自行运行/采用他们的想法。

【讨论】:

  • 到目前为止,Jamie 看起来很有趣。我还看到了可以解决我的问题的 Fluent Validation 框架。所以从表面上看,如果属性上有任何验证属性,那么将验证属性放在类上是错误的。此外,该框架似乎提供了一个很好的接口来进行我也实现的 jQuery 验证。
  • 我不会说将验证属性放在类上是错误的,因为每种情况都不同。我会说最好尽可能将它们放在属性上,以便用户获得更好的体验。
  • 我会支持 Jamie。更好的是,使用“伙伴类”方法将数据类和验证逻辑分开。
  • 又一次,应该授予的赏金未能获得奖励......新规则很糟糕。
  • 我得到了 1/2,它把我推到了 10k 以上,所以没有抱怨。我想我会跟进元数据;如果符合条件的答案是接受的答案,则自动奖励应奖励全部金额。
【解决方案2】:

要扩展指向Scott Guthrie's article 的链接,从MVC 3 开始,您可以通过实现IValidatableObject 接口来执行类级别验证。

这将在当前验证管道的上下文中工作,因此它可以嵌套在任意数量的自定义类和属性上,并继续返回可能的错误消息的完整数组。

对于您的类,放弃类级别的属性,并添加一个名为 Validate 的方法,如下所示:

public class EditSiteUser : IValidatableObject
{
    public int UserId { get; set; }

    [Required(ErrorMessage = "Du skal indtaste et brugernavn")]
    public string Username { get; set; }

    [Required(ErrorMessage = "Du skal indtaste en adgangskode")]
    public string Password { get; set; }

    [Required(ErrorMessage="Du skal bekræfte adgangskode")]
    public string PasswordConfirm { get; set; }

    [Required(ErrorMessage = "Du skal indtaste en e-mailadresse")]
    [Email(ErrorMessage = "Ugyldig e-mailadresse")]
    public string Email { get; set; }

    [Required(ErrorMessage="Du skal bekræfte e-mailadressen")]
    [Email(ErrorMessage="Ugyldig e-mailadresse")]
    public string EmailConfirm { get; set; }


    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    { 
      // put whatever class level validation you want here

      if (Email !== EmailConfirm)
      {
          yield return new ValidationResult("E-mailadresserne skal være ens", new[] {"EmailConfirm"})
      }

      if (Password !== PasswordConfirm)
      {
          yield return new ValidationResult("Adgangskoderne skal være ens", new[] {"PasswordConfirm"})
      }
    }

}

您可以继续yield return 发送任意数量的验证消息。

您可以使用@Html.ValidationSummary将它们全部显示在客户端上

如果您希望消息出现在特定控件旁边,ValidationResult 构造函数使用受影响属性的memberNames 进行重载,您可以使用@987654325 为该特定属性提供验证消息@HTML 助手是这样的:

@Html.ValidationMessageFor(Function(model) model.TestOne )

另外,值得一提的是,您可以使用CompareValidator 轻松确保两个不同属性的值相等。使用此注解的好处是它会自动知道如何在客户端和服务器上强制执行此操作,而添加 IValidatableObject 只会在服务器上运行。

[DataType(DataType.Password)]
public string Password { get; set; }

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

如需进一步阅读,请查看 Scott Guthrie 另一篇关于 class level validation 的详细信息。

【讨论】:

  • 对涉及多个属性的规则进行非常好的和简单的类验证。与面向类的 ValidationAttributes 不同,它允许您注意问题中涉及的属性。谢谢分享。
【解决方案3】:

从你的例子中,你喜欢有一个“确认其他输入框条目”框,正确的实现应该是

 [EqualTo("Email", ErrorMessage = "E-mailadresserne skal være ens")]
 public string EmailConfirm { get; set; }

因为“错误”是对确认框的验证。 或者换句话说, 您希望在确认框旁边显示错误消息,说明它与电子邮件框中的不同。

这会将验证配置放回属性,并解决您的问题。

【讨论】:

  • 我认为属性级验证属性只能访问其自身的值?
  • 啊,请参阅 Jamie Ide 的回答。需要在这里找到 MVC 万无一失的验证:foolproof.codeplex.com
猜你喜欢
  • 2011-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-03
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
  • 2015-11-30
相关资源
最近更新 更多