¿Cómo usar anotaciones de datos para hacer una validación condicional en el modelo?
Por ejemplo, supongamos que tenemos el siguiente modelo (Persona y Senior):
public class Person
{
[Required(ErrorMessage = "*")]
public string Name
{
get;
set;
}
public bool IsSenior
{
get;
set;
}
public Senior Senior
{
get;
set;
}
}
public class Senior
{
[Required(ErrorMessage = "*")]//this should be conditional validation, based on the "IsSenior" value
public string Description
{
get;
set;
}
}
Y la siguiente vista:
<%= Html.EditorFor(m => m.Name)%>
<%= Html.ValidationMessageFor(m => m.Name)%>
<%= Html.CheckBoxFor(m => m.IsSenior)%>
<%= Html.ValidationMessageFor(m => m.IsSenior)%>
<%= Html.CheckBoxFor(m => m.Senior.Description)%>
<%= Html.ValidationMessageFor(m => m.Senior.Description)%>
Me gustaría ser el campo obligatorio condicional de propiedad "Senior.Description" basado en la selección de la propiedad "IsSenior" (verdadero -> obligatorio). ¿Cómo implementar la validación condicional en ASP.NET MVC 2 con anotaciones de datos?
c#
asp.net-mvc
forms
validation
Peter Stegnar
fuente
fuente
Senior
objeto siempre es un senior, entonces, ¿por qué IsSenior puede ser falso en ese caso? No solo necesita que la propiedad 'Person.Senior' sea nula cuandoPerson.IsSenior
es falsa. O por qué no aplicar laIsSenior
propiedad como sigue:bool IsSenior { get { return this.Senior != null; } }
.Respuestas:
Hay una forma mucho mejor de agregar reglas de validación condicional en MVC3; haga que su modelo herede
IValidatableObject
e implemente elValidate
método:Lea más en Introducción a ASP.NET MVC 3 (Vista previa 1) .
fuente
ModelState.IsValid
, no llamar a Validar directamenteHe resuelto esto manejando el diccionario "ModelState" , que está contenido en el controlador. El diccionario ModelState incluye todos los miembros que deben validarse.
Aquí está la solución:
Si necesita implementar una validación condicional basada en algún campo (por ejemplo, si A = verdadero, entonces se requiere B), mientras se mantiene la mensajería de error a nivel de propiedad (esto no es cierto para los validadores personalizados que están a nivel de objeto) puede lograr esto manejando "ModelState", simplemente quitando validaciones no deseadas de él.
... en alguna clase ...
... la clase continúa ...
... En alguna acción del controlador ...
...
Con esto logramos la validación condicional, dejando todo lo demás igual.
ACTUALIZAR:
Esta es mi implementación final: he usado una interfaz en el modelo y el atributo de acción que valida el modelo que implementa dicha interfaz. La interfaz prescribe el método Validate (ModelStateDictionary modelState). El atributo en acción solo llama a Validate (modelState) en IValidatorSomething.
No quería complicar esta respuesta, por lo que no mencioné los detalles finales de implementación (que, al final, importan en el código de producción).
fuente
Tuve el mismo problema ayer, pero lo hice de una manera muy limpia que funciona tanto para la validación del lado del cliente como del lado del servidor.
Condición: según el valor de otra propiedad en el modelo, desea que se requiera otra propiedad. Aqui esta el codigo
Aquí PropertyName es la propiedad en la que desea establecer su condición. DesiredValue es el valor particular del PropertyName (propiedad) para el cual se debe validar su otra propiedad
Digamos que tienes lo siguiente
Por último, pero no menos importante, registre el adaptador para su atributo para que pueda hacer la validación del lado del cliente (lo puse en global.asax, Application_Start)
fuente
He estado usando este Nuget increíble que hace anotaciones dinámicas ExpressiveAnnotations
Podrías validar cualquier lógica con la que puedas soñar:
fuente
Puede deshabilitar los validadores condicionalmente eliminando errores de ModelState:
fuente
Gracias Merritt :)
Acabo de actualizar esto a MVC 3 en caso de que alguien lo encuentre útil: Validación condicional en ASP.NET MVC 3 .
fuente
Ahora hay un marco que realiza esta validación condicional (entre otras validaciones de anotación de datos útiles) fuera de la caja: http://foolproof.codeplex.com/
Específicamente, eche un vistazo al validador [RequiredIfTrue ("IsSenior")]. Lo coloca directamente en la propiedad que desea validar, de modo que obtiene el comportamiento deseado del error de validación asociado a la propiedad "Senior".
Está disponible como un paquete NuGet.
fuente
Debe validar a nivel de Persona, no a nivel de Senior, o Senior debe tener una referencia a su Persona principal. Me parece que necesita un mecanismo de autovalidación que defina la validación en la Persona y no en una de sus propiedades. No estoy seguro, pero no creo que DataAnnotations lo admita de forma inmediata. Lo que puedes hacer crea el tuyo propio
Attribute
queValidationAttribute
se puede decorar a nivel de clase y luego crear un validador personalizado que también permita que se ejecuten esos validadores a nivel de clase.Sé que Validation Application Block admite la autovalidación fuera de la caja, pero VAB tiene una curva de aprendizaje bastante empinada. Sin embargo, aquí hay un ejemplo usando VAB:
fuente
Tuve el mismo problema, necesitaba una modificación del atributo [Obligatorio]: hacer que el campo sea obligatorio en función de la solicitud http. La solución fue similar a la respuesta de Dan Hunex, pero su solución no funcionó correctamente (ver comentarios). No uso validación discreta, solo MicrosoftMvcValidation.js fuera de la caja. Aquí está. Implemente su atributo personalizado:
Luego debe implementar su proveedor personalizado para usarlo como un adaptador en su global.asax
Y modifique su global.asax con una línea
Y aquí está
La principal ventaja para mí es que no tengo que codificar un validador de cliente personalizado como en el caso de una validación discreta. funciona igual que [Obligatorio], pero solo en los casos que desee.
fuente
DataAnnotationsModelValidator
era exactamente lo que necesitaba ver. Gracias.Echa un vistazo a la validación condicional de Simon Ince en MVC .
Estoy trabajando en su proyecto de ejemplo en este momento.
fuente
Uso típico para la eliminación condicional del error del estado del modelo:
Ejemplo:
En su ejemplo, mantenga todo como está y agregue la lógica sugerida a la Acción de su Controlador. Supongo que su ViewModel pasado a la acción del controlador tiene los objetos Person y Senior Person con datos completados en ellos desde la IU.
fuente
Estoy usando MVC 5 pero podrías probar algo como esto:
En su caso, diría algo como "IsSenior == true". Entonces solo necesita verificar la validación en su acción de publicación.
fuente