9 votes

FluentValidation.Net ne produit pas de validation discrète côté client lors de l'utilisation de .SetValidator()

J'essaie de faire fonctionner la validation côté client pour une page qui utilise des modèles d'éditeurs.

Un exemple simplifié de mon modèle de vue est, par exemple, le suivant :

[Validator(typeof(ValidationTestModelValidator))]
public class ValidationTestModel
{
    public string Name { get; set; }

    public string Age { get; set; }

    public ChildModel Child { get; set; }
}

Le modèle de l'enfant est par exemple :

public class ChildModel
{
    public string ChildName { get; set; }

    public string ChildAge { get; set; }
}

Mon validateur est par exemple :

public class ValidationTestModelValidator : AbstractValidator<ValidationTestModel>
{
    public ValidationTestModelValidator()
    {
        RuleFor(m => m.Name)
            .NotEmpty()
            .WithMessage("Please enter the name");

        RuleFor(m => m.Age)
            .NotEmpty()
            .WithMessage("Please enter the age");

        RuleFor(m => m.Age)
            .Matches(@"\d*")
            .WithMessage("Must be a number");

        RuleFor(m => m.Child)
            .SetValidator(new ChildModelValidator());
    }
}

Et le validateur du modèle enfant est par exemple :

public class ChildModelValidator : AbstractValidator<ChildModel>
{
    public ChildModelValidator()
    {
        RuleFor(m => m.ChildName)
            .NotEmpty()
            .WithMessage("Please enter the name");

        RuleFor(m => m.ChildAge)
            .NotEmpty()
            .WithMessage("Please enter the age");

        RuleFor(m => m.ChildAge)
            .Matches(@"\d*")
            .WithMessage("Must be a number");
    }
}

J'ai enregistré FluentValidation.Net avec MVC3 en ajoutant ce qui suit à Application_Start() :

// Register FluentValidation.Net
FluentValidationModelValidatorProvider.Configure();

Cela génère une validation discrète côté client pour les deux propriétés Name et Age, mais rien pour les propriétés du ChildModel.

Une idée de ce que je fais de travers ?

Mise à jour : Cela semble fonctionner correctement si j'annote simplement le ChildModel avec l'attribut Validator, mais je veux appliquer la validation de manière conditionnelle, d'où l'utilisation de SetValidator().

1voto

Tz_ Points 1990

J'ai essayé d'analyser la documentation http://fluentvalidation.codeplex.com/wikipage?title=mvc&referringTitle=Documentation . Il indique que l'intégration MVC fonctionne par défaut sur la base des attributs, car sa fabrique de validateurs utilise l'attribut pour instancier le validateur approprié. Apparemment, il valide le ChildModel référencé par la propriété sur le modèle principal, mais il s'agit peut-être simplement d'une traversée récursive automatique de la structure du modèle pour générer le code de validation côté client. Il est donc possible qu'il utilise le même mécanisme pour localiser le validateur approprié pour le type ChildModel. Pourriez-vous tester ce qui se passe si vous supprimez la règle SetValidator (mais laissez l'attribut ChildModel), si les validateurs sont toujours générés sur la base de l'attribut ?

Il existe une liste explicite des validateurs pris en charge côté client, mais malheureusement SetValidator n'y est pas mentionné (ou expliqué), ce qui n'est pas bon signe.

La documentation indique également que les règles utilisant une condition ne sont pas prises en charge du côté client. Il est donc très probable que vous ne puissiez pas contourner ce problème en utilisant SetValidator (comme vous l'avez indiqué dans votre mise à jour).

Voir aussi cette discussion sur les règles conditionnelles côté client : http://fluentvalidation.codeplex.com/discussions/393596 . La suggestion était d'implémenter la règle conditionnelle en JS avec jQuery Validation, mais cela peut s'avérer compliqué si vous avez une validation complexe qui doit être ajoutée de manière conditionnelle.

Pourquoi ne pas le laisser ajouter les validateurs avec l'attribut, mais les supprimer ensuite d'une manière ou d'une autre ? Par exemple, en supprimant les attributs discrets des éléments par la suite ?

1voto

MarkG Points 986

Comme vous le soulignez dans votre mise à jour, vous devez décorer le type enfant avec le validateur si vous voulez émettre le balisage discret. Vous pouvez alors utiliser ce sous condition dans la classe du validateur "parent", soit en l'enveloppant dans un bloc if, soit en utilisant la méthode When() de FluentValidation pour utiliser une expression.

Notez également qu'il est possible d'enchaîner des règles pour les propriétés (c'est-à-dire en utilisant l'interface fluente) :

RuleFor(m => m.ChildName)
    .NotEmpty()
    .WithMessage("Please enter the name")
    .Matches(@"\d*")
    .WithMessage("Must be a number");

0voto

RezaRahmati Points 1807

Au cas où quelqu'un d'autre aurait le même problème :

Vous devez ajouter l'attribut validator à votre fichier ChildModel aussi

[Validator(typeof(ChildModelValidator))]
public class ChildModel

et de garder tous les autres codes tels quels, alors cela fonctionne du côté client

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X