Entiendo que IValidatableObject
se usa para validar un objeto de una manera que le permite a uno comparar propiedades entre sí.
Todavía me gustaría tener atributos para validar propiedades individuales, pero quiero ignorar fallas en algunas propiedades en ciertos casos.
¿Estoy tratando de usarlo incorrectamente en el siguiente caso? Si no, ¿cómo implemento esto?
public class ValidateMe : IValidatableObject
{
[Required]
public bool Enable { get; set; }
[Range(1, 5)]
public int Prop1 { get; set; }
[Range(1, 5)]
public int Prop2 { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (!this.Enable)
{
/* Return valid result here.
* I don't care if Prop1 and Prop2 are out of range
* if the whole object is not "enabled"
*/
}
else
{
/* Check if Prop1 and Prop2 meet their range requirements here
* and return accordingly.
*/
}
}
}
Cita de la publicación del blog de Jeff Handley sobre objetos de validación y propiedades con el validador :
Esto indica que lo que está intentando hacer no funcionará de inmediato porque la validación se cancelará en el paso 2. Podría intentar crear atributos que hereden de los integrados y verificar específicamente la presencia de una propiedad habilitada (a través de una interfaz) antes de realizar su validación normal. Alternativamente, podría poner toda la lógica para validar la entidad en el
Validate
método.fuente
Solo para agregar un par de puntos:
Debido a que la
Validate()
firma del método regresaIEnumerable<>
, esoyield return
puede usarse para generar perezosamente los resultados; esto es beneficioso si algunas de las comprobaciones de validación son intensivas en IO o CPU.Además, si está utilizando
MVC ModelState
, puede convertir las fallas del resultado de la validación enModelState
entradas de la siguiente manera (esto podría ser útil si está realizando la validación en un cuaderno de modelo personalizado ):fuente
Implementé una clase abstracta de uso general para validación
fuente
El problema con la respuesta aceptada es que ahora depende del llamador para que el objeto se valide correctamente. Quitaría RangeAttribute y haría la validación de rango dentro del método Validate o crearía un atributo personalizado que subclase RangeAttribute que tome el nombre de la propiedad requerida como argumento en el constructor.
Por ejemplo:
fuente
Me gustó la respuesta de cocogza, excepto esa base de llamadas. IsValid resultó en una excepción de desbordamiento de pila, ya que volvería a ingresar al método IsValid una y otra vez. Así que lo modifiqué para un tipo específico de validación, en mi caso fue para una dirección de correo electrónico.
¡Esto funciona mucho mejor! No se bloquea y produce un buen mensaje de error. ¡Espero que esto ayude a alguien!
fuente
Lo que no me gusta de iValidate es que parece ejecutarse DESPUÉS de todas las demás validaciones.
Además, al menos en nuestro sitio, volvería a ejecutarse durante un intento de guardar. Le sugiero que simplemente cree una función y coloque todo su código de validación en eso. Alternativamente para sitios web, puede tener su validación "especial" en el controlador después de crear el modelo. Ejemplo:
fuente