ASP.NET MVC: Validación personalizada por DataAnnotation

Tengo un modelo con 4 propiedades que son de tipo cadena. Sé que puede validar la longitud de una sola propiedad utilizando la anotación StringLength. Sin embargo, quiero validar la longitud de las 4 propiedades combinadas.

¿Cuál es la forma de MVC de hacer esto con la anotación de datos?

Pregunto esto porque soy nuevo en MVC y quiero hacerlo de la manera correcta antes de hacer mi propia solución.

Puede escribir un atributo de validación personalizado:

public class CombinedMinLengthAttribute: ValidationAttribute { public CombinedMinLengthAttribute(int minLength, params string[] propertyNames) { this.PropertyNames = propertyNames; this.MinLength = minLength; } public string[] PropertyNames { get; private set; } public int MinLength { get; private set; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var properties = this.PropertyNames.Select(validationContext.ObjectType.GetProperty); var values = properties.Select(p => p.GetValue(validationContext.ObjectInstance, null)).OfType(); var totalLength = values.Sum(x => x.Length) + Convert.ToString(value).Length; if (totalLength < this.MinLength) { return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName)); } return null; } } 

y luego puede tener un modelo de vista y decorar una de sus propiedades con él:

 public class MyViewModel { [CombinedMinLength(20, "Bar", "Baz", ErrorMessage = "The combined minimum length of the Foo, Bar and Baz properties should be longer than 20")] public string Foo { get; set; } public string Bar { get; set; } public string Baz { get; set; } } 

Modelo autovalidado

Su modelo debe implementar una interfaz IValidatableObject . Pon tu código de validación en el método Validate :

 public class MyModel : IValidatableObject { public string Title { get; set; } public string Description { get; set; } public IEnumerable Validate(ValidationContext validationContext) { if (Title == null) yield return new ValidationResult("*", new [] { nameof(Title) }); if (Description == null) yield return new ValidationResult("*", new [] { nameof(Description) }); } } 

Tenga en cuenta: esta es una validación del lado del servidor . No funciona en el lado del cliente. Su validación se realizará solo después del envío del formulario.

ExpresiveAnnotations le da tal posibilidad:

 [Required] [AssertThat("Length(FieldA) + Length(FieldB) + Length(FieldC) + Length(FieldD) > 50")] public string FieldA { get; set; } 

Fondo:

Se requieren validaciones de modelo para garantizar que los datos recibidos que recibimos sean válidos y correctos para que podamos realizar el procesamiento posterior con estos datos. Podemos validar un modelo en un método de acción. Los atributos de validación integrados son Compare, Range, RegularExpression, Required, StringLength. Sin embargo, podemos tener escenarios en los que requiriéramos atributos de validación distintos a los incorporados.

Atributos de validación personalizados

 public class EmployeeModel { [Required] [UniqueEmailAddress] public string EmailAddress {get;set;} public string FirstName {get;set;} public string LastName {get;set;} public int OrganizationId {get;set;} } 

Para crear un atributo de validación personalizado, deberá derivar esta clase de ValidationAttribute.

 public class UniqueEmailAddress : ValidationAttribute { private IEmployeeRepository _employeeRepository; [Inject] public IEmployeeRepository EmployeeRepository { get { return _employeeRepository; } set { _employeeRepository = value; } } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var model = (EmployeeModel)validationContext.ObjectInstance; if(model.Field1 == null){ return new ValidationResult("Field1 is null"); } if(model.Field2 == null){ return new ValidationResult("Field2 is null"); } if(model.Field3 == null){ return new ValidationResult("Field3 is null"); } return ValidationResult.Success; } } 

Espero que esto ayude. ¡Salud!

Referencias

  • Code Project – Atributo de validación personalizado en ASP.NET MVC3
  • Haacked – Validación personalizada de ASP.NET MVC 2

Para mejorar la respuesta de Darin, puede ser un poco más corto:

 public class UniqueFileName : ValidationAttribute { private readonly NewsService _newsService = new NewsService(); public override bool IsValid(object value) { if (value == null) { return false; } var file = (HttpPostedFile) value; return _newsService.IsFileNameUnique(file.FileName); } } 

Modelo:

 [UniqueFileName(ErrorMessage = "This file name is not unique.")] 

Tenga en cuenta que se requiere un mensaje de error, de lo contrario, el error estará vacío.

Un poco tarde para responder, pero para quién está buscando. Puede hacer esto fácilmente mediante el uso de una propiedad adicional con la anotación de datos:

 public string foo { get; set; } public string bar { get; set; } [MinLength(20, ErrorMessage = "too short")] public string foobar { get { return foo + bar; } } 

Eso es todo lo que es realmente. Si realmente desea mostrar en un lugar específico el error de validación también, puede agregar esto en su vista:

 @Html.ValidationMessage("foobar", "your combined text is too short") 

Hacer esto en la vista puede ser útil si quieres hacer localización.

¡Espero que esto ayude!