使用 DataAnnotations 比较两个模型属性

Posted

技术标签:

【中文标题】使用 DataAnnotations 比较两个模型属性【英文标题】:Using DataAnnotations to compare two model properties 【发布时间】:2011-06-23 17:03:26 【问题描述】:

我将如何编写一个比较两个字段的自定义 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)
    
        // ??
    

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

【问题讨论】:

【参考方案1】:

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

那么你的代码应该是这样的:

using System.Web.Mvc;

。 . . .

[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; 

【讨论】:

在这种情况下,您可以为第二个属性保存Required 属性,因为您已经强制与第一个属性进行比较,实际上是Required。 请注意,从 C#6.0 开始,现在可以使用 nameof 关键字,而不是使用“魔术字符串”作为属性名称。这可以更好/更轻松地重构任何相关属性,因为它使用的是强类型属性名称(并且您不必记住更新魔术字符串(就像我做过几次一样))。另外,如果您以某种方式错过了一个,编译器会出错 - 从而使其“万无一失”。根据@Janx 的回答使用示例:[CompareAttribute(nameof(NewPassword), ErrorMessage = "Passwords don't match.")]【参考方案2】:

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

【讨论】:

【参考方案3】:

这是达林答案的更长版本:

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");
    

及用法:

[MetadataType(typeof(FooMD))]
public partial class Foo

     ... functions ...


[Custom]
public class FooMD

     ... other data annotations ...

错误会显示在@html.ValidationSummary(false)

【讨论】:

【参考方案4】:

您可以有一个自定义验证属性并将其应用于模型而不是单个属性。这是example,你可以看看。

【讨论】:

【参考方案5】:

对于将来研究这个问题的人,我试图编写一个验证属性,如果对象的属性是某个值,它将评估正则表达式。就我而言,如果地址是送货地址,我不希望启用邮政信箱,所以这是我想出的:

用法

[Required]
public EAddressType addressType  get; set;  //Evaluate Validation attribute against this

[EvaluateRegexIfPropEqualsValue(Constants.NOT_PO_BOX_REGEX, "addressType", EAddressType.Shipping, ErrorMessage = "Unable to ship to PO Boxes or APO addresses")]
public String addressLine1  get; set; 

这是验证属性的代码:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class EvaluateRegexIfPropEqualsValue : ValidationAttribute

    Regex _regex;
    string _prop;
    object _targetValue;

    public EvaluateRegexIfPropEqualsValue(string regex, string prop, object value)
    
        this._regex = new Regex(regex);
        this._prop = prop;
        this._targetValue = value;
    

    bool PropertyContainsValue(Object obj)
    
        var propertyInfo = obj.GetType().GetProperty(this._prop);
        return (propertyInfo != null && this._targetValue.Equals(propertyInfo.GetValue(obj, null)));
    

    protected override ValidationResult IsValid(object value, ValidationContext obj)
    
        if (this.PropertyContainsValue(obj.ObjectInstance) && value != null && !this._regex.IsMatch(value.ToString()))
        
            return new ValidationResult(this.ErrorMessage);
        
        return ValidationResult.Success;
    

【讨论】:

【参考方案6】:

如果你们正在使用 MVC 4,请尝试此代码..它将解决您的错误..

请创建一个元数据类而不是部分类实现 comfirmemail 属性。查看下面的代码了解更多详情。

using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using StringlenghtMVC.Comman;
    using System.Web.Mvc;

using System.Collections;

    [MetadataType(typeof(EmployeeMetaData))] //here we call metadeta class
    public partial class Employee
    
        public int Id  get; set; 
        public string Name  get; set; 
        public string Email  get; set; 
        public Nullable<int> Age  get; set; 
        public string Gender  get; set; 
        public Nullable<System.DateTime> HireDate  get; set; 

       //[CompareAttribute("Email")]
        public string ConfirmEmail  get; set; 
    

    public class EmployeeMetaData
    
        [StringLength(10, MinimumLength = 5)]
        [Required]
        //[RegularExpression(@"(([A-za-Z]+[\s]1[A-za-z]+))$", ErrorMessage = "Please enter Valid Name")]
        public string Name  get; set; 

        [Range(1, 100)]
        public int Age  get; set; 
        [CurrentDate]
        [DisplayFormat(DataFormatString = "0:d", ApplyFormatInEditMode = true)]
        public DateTime HireDate  get; set; 

        //[RegularExpression(@"^[\w-\._\%]+@(?:[\w]2,6$")]
        public string Email  get; set; 

        [System.Web.Mvc.CompareAttribute("Email")]
        public string ConfirmEmail  get; set; 


    

【讨论】:

以上是关于使用 DataAnnotations 比较两个模型属性的主要内容,如果未能解决你的问题,请参考以下文章

使用 DataAnnotations(数据注解)实现通用模型数据校验

EF实体配置

如何使用 DataAnnotations 处理 ASP.NET MVC 2 中的布尔值/复选框?

DataAnnotations StringLength 属性 MVC - 没有最大值

C# REST API - 如何使用错误代码扩展模型状态错误

Asp.Net MVC 中 DataAnnotations StringLength 中文本框的 maxlength 属性