MVC tiene un gancho para proporcionar su propio ModelValidatorProvider. De forma predeterminada, MVC 2 usa una subclase de ModelValidatorProvider llamada DataAnnotationsModelValidatorProvider que puede usar los atributos System.DataAnnotations.ComponentModel.ValidationAttribute para la validación.
El DataAnnotationsModelValidatorProvider utiliza la reflexión para encontrar todos los ValidationAttributes y simplemente recorre la colección para validar sus modelos. Todo lo que necesita hacer es anular un método llamado GetValidators e inyectar sus propios atributos de la fuente que elija. Utilizo esta técnica para hacer validaciones de convenciones, las propiedades con el atributo DataType.Email siempre se pasan a través de una expresión regular, y utilizo esta técnica para extraer información de la base de datos para aplicar validaciones más restrictivas para usuarios "no poderosos".
el siguiente ejemplo se dice simplemente "siempre que las propiedades requeridas FirstName":
public class CustomMetadataValidationProvider : DataAnnotationsModelValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
//go to db if you want
//var repository = ((MyBaseController) context.Controller).RepositorySomething;
//find user if you need it
var user = context.HttpContext.User;
if (!string.IsNullOrWhiteSpace(metadata.PropertyName) && metadata.PropertyName == "FirstName")
attributes = new List<Attribute>() {new RequiredAttribute()};
return base.GetValidators(metadata, context, attributes);
}
}
Todo lo que tiene que hacer es registrar el proveedor en su archivo Global.asax.cs:
protected void Application_Start()
{
ModelValidatorProviders.Providers.Add(new CustomMetadataValidationProvider());
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
El resultado final:
w ITH este modelo:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Birthday { get; set; }
}
esto es genial jfar! ;) Creo que me salvaste una inmersión profunda en VAB .. – mare
Un problema con el código de ejemplo en esta respuesta es que los atributos se pueden procesar dos veces: una vez por tu subclase de 'DataAnnotationsModelValidatorProvider' y una por la preexistente. Esto puede conducir a errores. Creo que es mejor pasar atributos que está agregando a la llamada a 'base.GetValidators' para evitar esto. – Sam
Además, en ASP.NET MVC 4 (y posiblemente otros), 'base.GetValidators' automáticamente agrega' RequiredAttribute' cuando 'metadata.IsRequired' es' true'. Una forma de eludir esto es establecer 'metadata.IsRequired' en' false' antes de llamar a 'base.GetValidators'. Puede volver a establecer el valor original después de la llamada. – Sam