使用 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(数据注解)实现通用模型数据校验
如何使用 DataAnnotations 处理 ASP.NET MVC 2 中的布尔值/复选框?
DataAnnotations StringLength 属性 MVC - 没有最大值
C# REST API - 如何使用错误代码扩展模型状态错误
Asp.Net MVC 中 DataAnnotations StringLength 中文本框的 maxlength 属性