J'ai essayé de créer une règle FluentValidation qui vérifie si l'instance d'un objet en cours de validation n'est pas nulle avant de valider ses propriétés.
Je préférerais encapsuler cette validation nulle dans le validateur plutôt que de le faire dans le code appelant.
Voir l'exemple de code ci-dessous avec des commentaires pour lesquels la logique requise est requise:
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;
}
}
}
Ma question est donc la suivante: comment puis-je vérifier dans le constructeur CustomerValidator () que l'instance actuelle du client n'est pas nulle et interrompre le traitement de la règle s'il est null ?
Merci d'avance.
Vous devriez pouvoir remplacer la méthode Validate
dans votre classe 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);
}
}
Je ne peux pas vraiment tester cela pour l'instant, mais vous pouvez soit essayer de remplacer Validate
, soit inclure les règles dans le bloc When
:
public CustomerValidator()
{
When(x => x != null, () => {
RuleFor(x => x.Surname).NotEmpty();
//etc.
});
}
Pour ceux qui utilisent la version> 6.2.1, vous devez remplacer cette signature afin d'obtenir le même résultat que @chrispr:
public override ValidationResult Validate(ValidationContext<T> context)
{
return (context.InstanceToValidate == null)
? new ValidationResult(new[] { new ValidationFailure("Property", "Error Message") })
: base.Validate(context);
}
J'ai hérité du abstractValidator courant et créé une classe NullReferenceAbstractValidator à la place:
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);
}
}
puis hérité de cette classe avec chaque validateur ayant besoin d'une vérification de référence nulle:
public class UserValidator : NullReferenceAbstractValidator<User>
Comme les solutions ci-dessus ne fonctionnaient pas pour moi (FluentValidation, Version = 6.2.1.0 pour Net45), je publie ce que j'ai fait. C'est juste un simple remplacement/wrapper pour la méthode d'extension 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);
}
}
Utilisez le mode Cascade.
Voici l'exemple de la documentation .
RuleFor(x => x.Surname).Cascade(CascadeMode.StopOnFirstFailure).NotNull().NotEqual("foo");
Aussi de la documentation:
Si le validateur NotNull échoue, le validateur NotEqual ne sera pas réalisé. Ceci est particulièrement utile si vous avez une chaîne complexe où chaque validateur dépend du validateur précédent pour réussir.
Au moyen de Custom (). Cela peut aussi être très utile lorsque la validation d’un autre champ est basée sur la validation de votre champ actuel.
ruleBuilder.Custom((obj, context) =>
{
if (obj != null)
{
var propertyName = <field where should be validation>;
context.AddFailure(propertyName, "'Your field name' Your validation message.");
}
});
Remplacez EnsureInstanceNotNull comme ci-dessous
protected override void EnsureInstanceNotNull(object instanceToValidate)
{
if(instanceToValidate==null)
throw new ValidationException("Customer can not be null");
}
Ceci est une publication plus ancienne, mais vous souhaitez mettre à jour les réponses pour inclure les éléments suivants de la documentation de FluentValidation:
Utiliser PreValidate
Si vous devez exécuter un code spécifique chaque fois qu'un validateur est appelé, vous pouvez le faire en substituant la méthode PreValidate. Cette méthode utilise un ValidationContext ainsi qu'un ValidationResult, que vous pouvez utiliser pour personnaliser le processus de validation.
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;
}
}