jeudi 29 septembre 2011 12:35
tja
[ASP.NET MVC 3] Deep Dive Injection de Dépendance – ModelValidation – Partie 8
Cet article fait partie d’une série consacrée à l’injection de dépendance dans MVC 3 :
Le code source de cet article se trouve ici
.
ModelValidation et DI.
C’est un service d’enregistrement multiple. Le point d’enregistrement statique étant la collection ModelValidatorProviders.Providers.
MVC 2 : introduction de ModelValidatorProvider qui permet d’influencer la validation côté client et côté serveur. Il faut juste implémenter une classe qui dérive de celle-ci.
MVC 3 : Les validators sont localisables via le DependencyResolver.
Les fournisseurs de Model validator, analysent les modèles et retournent les validators qui s’assurent que les modèles sont valides (possible de retourner les clients validation hints consommés par du JS).
Nouveautés MVC 3 : La logique dans ModelValidatorProviderCollection qui implémente ModelValidatorProviders.Providers a été mise à jour pour consulter le DependencyResolver en faisant appel vers GetServices(typeof(ModelValidatorProvider)) et ajoutant les services trouvés à la liste des services enregistrés statiquement. Tous les validators enregistrés participent à la validation.
Afin d’écrire votre propre validator de modèle, la chose à faire est de dériver votre nouvelle classe de la classe abstraite ModelValidatorProvider et d’implémenter sa méthode unique GetValidators :
1: public abstract class ModelValidatorProvider
2: {
3: public abstract IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context);
4: }
Cette méthode est assez simple. Etant donnée le cotexte du contrôleur (ControllerContext) qui n’est rien d’autre que le contexte d’appel de la requête Http courante et le ModelMetadata qui décrit l’objet qui doit être validé vous devez retourner 0 ou plus de validators qui seront exécutés pour valider votre modèle.
Créer son propre validator de modèle.
Un validator est une classe dérivée de la classe abstraite ModelValidator. Cette classe accepte une instance de ModelMetadata et de ControllerContext comme arguments du constructeur. Pour écrire son validator de modèle il faut implémenter la méthode Validate pour la validation côté serveur et éventuellement la méthode GetClientValidationRules pour supporter la validation côté client.
Nous allons dans un premier temps implémenter notre propre validator provider et pour cela nous n’allons pas dériver directement de la classe ModelValidatorProvider mais de la classe AssociatedModelValidator. Cette classe apporte quelques fonctionnalités de base comme la lecture des attributs attachés au modèle.
Pour notre application d’exemple nous allons utiliser le même modèle que dans le post précédent : http://blogs.developpeur.org/tja/archive/2011/09/14/asp-net-mvc-3-deep-dive-injection-de-d-pendance-modelmetadata-partie-7.aspx.
Pour rappel, le modèle ressemble à ceci :

Nous n’allons pas établir une convention spéciale de validation mais à titre d’exemple nous allons imaginer que lorsqu’une propriété du modèle s’appelle “PostTitle” nous allons vérifier que la valeur est requise, sinon la validation échoue.
Tout d’abord créons notre Provider :

Comme vous pouvez le constater, le code est ultra simple. Lors de la validation du modèle les providers de validation ont la possibilité de renvoyer tous les validators lorsque certaines conditions sont rencontrées. Dans notre cas la condition est le nom de la propriété du modèle “PostTitle”. Lorsqu’une telle propriété est rencontrée nous allons vérifier que sa valeur est bien renseignée (ce qui revient à décorer la propriété avec l’attribut Required en temps normal). Lorsque cette condition est rencontrée nous renvoyons le validator PostTitleRequiredValidator pour valider la données de la propriété. Voici à quoi ressemble cette classe :

Comme vous pouvez le constater, nous dérivons notre classe de la classe abstraite ModelValidator et implémentons les méthodes Validate pour la validation côté serveur et éventuellement GetClientValidationRules pour supporter la validation côté client.
Tout ce qui nous reste à faire maintenant c’est d’enregistrer notre validator :
1. Enregistrement statique
1: // enregistrement statique
2: ModelValidatorProviders.Providers.Add(new ConventionValidatorProvider());
Nous ajoutons tout simplement l’instance de notre provider dans la collection statique des providers.
2. Enregistrement dynamique
1: IUnityContainer container = new UnityContainer();
2:
3: // enregistrement dynamique
4: container.RegisterType<ModelValidatorProvider, ConventionValidatorProvider>("convention");
5:
6: DependencyResolver.SetResolver(new UnityDependencyResolver(container));
A la ligne 5 nous enregistrons un mapping nommé qui est nécessaire pour notre implémentation de DependencyResolver avec Unity que j’explique dans ce post : [ASP.NET MVC 3] Unity et DependencyResolver – Enregistrement des services multiples.
Il ne nous reste à présent de tester notre implémentation :

Lorsque je clique sur le bouton “Save” j’obtiens l’erreur “Ce champ est requis !!!” qui provient de notre validator personnalisé.
Comme vous pouvez le constater il n’est pas difficile d’étendre le fonctionnement normal de MVC quant il s’agit de la validation.
Dans le prochain post je vais parler de ValueProviders.
// Thomas
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :