使用DataAnnotations比较两个模型属性

Sco*_*ott 38 c# validation asp.net-mvc data-annotations

我如何编写一个比较两个字段的自定义ValidationAttribute?这是常见的"输入密码","确认密码"方案.我需要确保两个字段相同并保持一致,我想通过DataAnnotations实现验证.

所以在伪代码中,我正在寻找一种方法来实现如下所示:

public class SignUpModel
{
    [Required]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [Required]
    [Display(Name = "Re-type Password")]
    [Compare(CompareField = Password, ErrorMessage = "Passwords do not match")]
    public string PasswordConfirm { get; set; }
}

public class CompareAttribute : ValidationAttribute
{
    public CompareAttribute(object propertyToCompare)
    {
        // ??
    }

    public override bool IsValid(object value)
    {
        // ??
    }
}
Run Code Online (Sandbox Code Playgroud)

所以问题是,我如何编码[Compare] ValidationAttribute?

Jan*_*ela 58

确保您的项目引用system.web.mvc v3.xxxxx.

然后你的代码应该是这样的:

using System.Web.Mvc;
Run Code Online (Sandbox Code Playgroud)

....

[Required(ErrorMessage = "This field is required.")]    
public string NewPassword { get; set; }

[Required(ErrorMessage = "This field is required.")]
[Compare(nameof(NewPassword), ErrorMessage = "Passwords don't match.")]
public string RepeatPassword { get; set; }
Run Code Online (Sandbox Code Playgroud)

  • 请注意,从C#6.0开始,现在可以使用`nameof`关键字,而不是使用"魔术字符串"作为属性名称.这样可以更好/更容易地重构任何相关属性,因为它使用的是强类型属性名称(而且可以节省您必须记住更新魔术字符串(因为我已经做了几次)).另外,如果您错过了一个编译器将会出错 - 不知何故 - 从而使其"万无一失".根据@ Janx的答案使用示例:`[CompareAttribute(nameof(NewPassword),ErrorMessage ="密码不匹配.")]` (3认同)
  • 在这种情况下,您可以自己保存第二个属性的Required属性,因为您已经强制执行与第一个属性的比较,而该属性实际上是必需的. (2认同)

Joe*_*ano 30

ASP.NET MVC 3 Framework中有一个CompareAttribute来执行此操作.如果您正在使用ASP.NET MVC 2并以.Net 4.0为目标,那么您可以查看ASP.NET MVC 3源代码中的实现.


And*_*nna 7

这是Darin答案的较长版本:

public class CustomAttribute : ValidationAttribute
{    
    public override bool IsValid(object value)
    {
        if (value.GetType() == typeof(Foo))
        {
           Foo bar = (Foo)value;
           //compare the properties and return the result
        }

        throw new InvalidOperationException("This attribute is only valid for Foo objects");
    }
}
Run Code Online (Sandbox Code Playgroud)

和用法:

[MetadataType(typeof(FooMD))]
public partial class Foo
{
     ... functions ...
}

[Custom]
public class FooMD
{
     ... other data annotations ...
}
Run Code Online (Sandbox Code Playgroud)

错误将显示在 @Html.ValidationSummary(false)