c# - dataannotations - Regla de FluentValidation para objeto nulo
fluent validation mvc (9)
Anular AsegurarInstanciaNotNull como abajo
protected override void EnsureInstanceNotNull(object instanceToValidate)
{
if(instanceToValidate==null)
throw new ValidationException("Customer can not be null");
}
He estado intentando averiguar cómo crear una regla FluentValidation que compruebe si la instancia de un objeto que está validando no es nula, antes de validar sus propiedades.
Prefiero encapsular esta validación nula en el Validador en lugar de hacerlo en el código de llamada.
Vea el código de ejemplo a continuación con comentarios donde se necesita la lógica requerida:
namespace MyNamespace
{
using FluentValidation;
public class Customer
{
public string Surname { get; set; }
}
public class CustomerValidator: AbstractValidator<Customer>
{
public CustomerValidator()
{
// Rule to check the customer instance is not null.
// Don''t continue validating.
RuleFor(c => c.Surname).NotEmpty();
}
}
public class MyClass
{
public void DoCustomerWork(int id)
{
var customer = GetCustomer(id);
var validator = new CustomerValidator();
var results = validator.Validate(customer);
var validationSucceeded = results.IsValid;
}
public Customer GetCustomer(int id)
{
return null;
}
}
}
Entonces, mi pregunta es ¿cómo verifico en el constructor CustomerValidator () que la instancia actual del cliente no es nula y aborta el procesamiento adicional de reglas si es nula ?
Gracias por adelantado.
Como las soluciones anteriores no me funcionaron (FluentValidation, versión = 6.2.1.0 para Net45), estoy publicando lo que hice. Esto es solo un simple reemplazo / envoltorio para el método de extensión ValidateAndThrow
.
public static class ValidatorExtensions
{
public static void ValidateAndThrowNotNull<T>(this IValidator<T> validator, T instance)
{
if (instance == null)
{
var validationResult = new ValidationResult(new[] { new ValidationFailure("", "Instance cannot be null") });
throw new ValidationException(validationResult.Errors);
}
validator.ValidateAndThrow(instance);
}
}
Debería poder anular el método Validate
en su clase CustomerValidator
.
public class CustomerValidator: AbstractValidator<Customer>
{
// constructor...
public override ValidationResult Validate(Customer instance)
{
return instance == null
? new ValidationResult(new [] { new ValidationFailure("Customer", "Customer cannot be null") })
: base.Validate(instance);
}
}
Esta es una publicación anterior, pero desea actualizar las respuestas para incluir lo siguiente de la documentación de FluentValidation:
Utilizando PreValidate
Si necesita ejecutar un código específico cada vez que se invoca un validador, puede hacerlo anulando el método PreValidate. Este método toma un ValidationContext así como un ValidationResult, que puede utilizar para personalizar el proceso de validación.
public class MyValidator : AbstractValidator<Person> { public MyValidator() { RuleFor(x => x.Name).NotNull(); } protected override bool PreValidate(ValidationContext<Person> context, ValidationResult result) { if (context.InstanceToValidate == null) { result.Errors.Add(new ValidationFailure("", "Please ensure a model was supplied.")); return false; } return true; } }
Heredé del fluido AbstractValidator y creé una clase NullReferenceAbstractValidator en su lugar:
public class NullReferenceAbstractValidator<T> : AbstractValidator<T>
{
public override ValidationResult Validate(T instance)
{
return instance == null
? new ValidationResult(new[] { new ValidationFailure(instance.ToString(), "response cannot be null","Error") })
: base.Validate(instance);
}
}
y luego se heredó de esa clase con cada validador que necesitaba una verificación de referencia nula:
public class UserValidator : NullReferenceAbstractValidator<User>
Para aquellos que usan la versión> 6.2.1, debe anular esta firma en su lugar, para lograr lo mismo que @chrispr:
public override ValidationResult Validate(ValidationContext<T> context)
{
return (context.InstanceToValidate == null)
? new ValidationResult(new[] { new ValidationFailure("Property", "Error Message") })
: base.Validate(context);
}
Por medio de Custom (). También puede ser muy útil cuando la validación de otro campo se basa en la validación de su campo actual.
ruleBuilder.Custom((obj, context) =>
{
if (obj != null)
{
var propertyName = <field where should be validation>;
context.AddFailure(propertyName, "''Your field name'' Your validation message.");
}
});
Realmente no puedo probar eso ahora, pero puedes intentar anular Validate
o incluir las reglas en el bloque When
:
public CustomerValidator()
{
When(x => x != null, () => {
RuleFor(x => x.Surname).NotEmpty();
//etc.
});
}
Utilice el modo en cascada.
Aquí está el ejemplo de la documentation .
RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().NotEqual("foo");
También a partir de la documentación:
Si el validador NotNull falla, el validador NotEqual no se ejecutará. Esto es particularmente útil si tiene una cadena compleja donde cada validador depende del validador anterior para tener éxito.