ASP.NET MVC: Validación personalizada mediante anotación de datos
Tengo un Modelo con 4 propiedades que son de tipo cadena. Sé que puedes validar la longitud de una sola propiedad usando la anotación StringLength. Sin embargo, quiero validar la longitud de las 4 propiedades combinadas.
¿Cuál es la forma 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 crear mi propia solución.
Podrías 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<string>();
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 podrías 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 Validate
método:
public class MyModel : IValidatableObject
{
public string Title { get; set; }
public string Description { get; set; }
public IEnumerable<ValidationResult> 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 del lado del cliente. Su validación se realizará solo después del envío del formulario.
ExpressiveAnnotations le ofrece esa posibilidad:
[Required]
[AssertThat("Length(FieldA) + Length(FieldB) + Length(FieldC) + Length(FieldD) > 50")]
public string FieldA { get; set; }
Para mejorar la respuesta de Darin, puede ser un poco más corta:
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.