web-dev-qa-db-fra.com

Règle FluentValidation pour plusieurs propriétés

J'ai un FluentValidator qui a plusieurs propriétés comme Zip et comté, etc. Je veux créer une règle qui prend deux propriétés comme une construction RuleFor

public class FooArgs
{
    public string Zip { get; set; }
    public System.Guid CountyId { get; set; }
}

public class FooValidator : AbstractValidator<FooArgs>
{
    RuleFor(m => m.CountyId).Must(ValidZipCounty).WithMessage("wrong Zip County");
}

Cela fonctionne mais je veux passer Zip et comté à la rue pour valider. Quelle est la meilleure méthode pour y parvenir?

37
Sofia Khwaja

Il existe une surcharge Must qui vous fournit également l'objet FooArgs documenté ici . Il vous permet de passer facilement les deux arguments dans votre méthode comme ceci:

RuleFor(m => m.CountyId).Must((fooArgs, countyId) =>
    ValidZipCounty(fooArgs.Zip, countyId))
    .WithMessage("wrong Zip County");
39
bpruitt-goddard

Je viens de tomber sur cette vieille question et je pense avoir une réponse plus simple. Vous pouvez facilement passer tout votre objet dans votre règle de validation personnalisée en simplifiant le paramètre à RuleFor par exemple.

RuleFor(m => m).Must(fooArgs =>
    ValidZipCounty(fooArgs.Zip, fooArgs.countyId))
    .WithMessage("wrong Zip County");

Si la méthode ValidZipCountry est locale à votre validateur et que vous pouvez modifier sa signature pour prendre un FooArgs, le code se simplifie jusqu'à

RuleFor(m => m).Must(ValidZipCounty).WithMessage("wrong Zip County");

Le seul inconvénient est que le PropertyName dans l'erreur de validation résultante sera une chaîne vide. Cela peut entraîner un problème pour votre code d'affichage de validation. Cependant, il n'est pas vraiment clair à quelle propriété l'erreur appartient aussi, ContryId ou Zip, donc cela a du sens.

15
Alan Hinton

Qu'en est-il de:

RuleFor(m => new {m.CountyId, m.Zip}).Must(x => ValidZipCounty(x.Zip, x.CountyId))
                                     .WithMessage("wrong Zip County");
12
Matías Romero

Dans mon cas, je devais marquer une propriété comme requis (x.RequiredProperty dans l'exemple ci-dessous) si une autre propriété n'était pas nulle (x.ParentProperty dans l'exemple ci-dessous). J'ai fini par utiliser la syntaxe When:

RuleFor(x => x.RequiredProperty).NotEmpty().When(x => x.ParentProperty != null);

Ou si vous avez plus d'une règle pour une clause When commune, vous pouvez l'écrire comme suit:

When(x => x.ParentProperty != null, () =>
{
    RuleFor(x => x.RequiredProperty).NotEmpty();
    RuleFor(x => x.OtherRequiredProperty).NotEmpty();
});

La définition de la syntaxe When est la suivante:

/// <summary>
/// Defines a condition that applies to several rules
/// </summary>
/// <param name="predicate">The condition that should apply to multiple rules</param>
/// <param name="action">Action that encapsulates the rules.</param>
/// <returns></returns>
public IConditionBuilder When (Func<T, bool> predicate, Action action);
1
Francesco D.M.