Usando DataAnnotations para comparar dos propiedades del modelo

¿Cómo hago para escribir un atributo de validación personalizado que compare dos campos? Este es el escenario común de “ingresar contraseña”, “confirmar contraseña”. Necesito estar seguro de que los dos campos son iguales y para mantener las cosas coherentes, quiero implementar la validación a través de DataAnnotations.

Entonces, en pseudocódigo, estoy buscando una manera de implementar algo como lo siguiente:

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) { // ?? } } 

Entonces la pregunta es, ¿cómo codifico el atributo ValidationAttribute [Compare]?

Hay un atributo de comparación en ASP.NET MVC 3 Framework que hace esto. Si está utilizando ASP.NET MVC 2 y está apuntando a .Net 4.0, podría ver la implementación en el código fuente de ASP.NET MVC 3.

Asegúrese de que su proyecto haga referencia a system.web.mvc v3.xxxxx.

Entonces tu código debería ser algo como esto:

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

Esta es una versión más larga de la respuesta de 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"); } } 

y uso:

 [MetadataType(typeof(FooMD))] public partial class Foo { ... functions ... } [Custom] public class FooMD { ... other data annotations ... } 

El error se mostrará en @Html.ValidationSummary(false)

Podría tener un atributo de validación personalizado y aplicarlo en el modelo y no en propiedades individuales. Aquí hay un ejemplo que puede echar un vistazo.

Si están usando MVC 4, por favor intente este código … resolverá su error …

por favor haga una Metadataclase que en la clase parcial implemente las propiedades de comfirmemail. Verifique el código de abajo para más detalles.

 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 Age { get; set; } public string Gender { get; set; } public Nullable 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; } } 

Para las personas futuras que miran este problema, estaba tratando de escribir un atributo de validación que evaluaría una expresión regular si la propiedad de un objeto tuviera un cierto valor. En mi caso, si una dirección era una dirección de envío, no quería habilitar los apartados de correos, así que esto es lo que se me ocurrió:

Uso

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

Y aquí está el código para el atributo de validación:

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