ASP.NET Core : Validation partagée avec React - partie 1
Dans une SPA (Single Page Application), il est souvent nécessaire de vérifier 2 fois la donnée :
- Une fois côté client, pour pouvoir présenter une réponse visuelle à l'utilisateur si le format des données n'est pas bon,
- Une fois côté serveur pour protéger le "vrai point d'entrée" du système ainsi que l'intégrité des données (en cas de modification malicieuse des scripts clients, mauvaise utilisation, etc.)
À ce sujet, j'ai pu échanger avec mes chers collègues Jonathan, Hamza et Benoit à ce sujet, et avec l'aide de Zack, nous avons pu mettre en place un système qui permet de ne définir qu'une seule fois les règles de validation et les répercuter à la fois côté client et serveur.
Principes du système de validation partagée
- Les validations sont définies côté serveur, via la librairie
FluentValidation
- On définit un
Endpoint
qui va, parréflexion
, récupérer tous les validateurs et va renvoyer leur description au format JSON - La SPA
react
va récupérer les règles de validation au démarrage de l'application, puis transformer ensuite toutes ces règles enValidationRules
compréhensibles par la librairiereact-hook-form
- Il ne reste plus qu'à lier nos données à valider aux règles de validation correspondantes, et voilà! Le tour est joué!
Il est à noter cependant que la mise en place d'un tel système a un petit coût d'entrée ainsi que de maintenance, aussi le retour sur investissement se voit plus sur des applications assez conséquentes et/ou possédant de nombreuses données à valider (ce qui, vous en conviendrez, arrive assez souvent :))
Exemple de rendu simple une fois tout le système mis en place.
Une mise en place d'exemple du système est disponible sur Github et sera référencée à maintes reprises durant ces articles.
L'explication du système en entier étant un peu longue, voyons dans ce premier article la mise en place de la partie serveur, côté aspnetcore.
Définition des règles de validation avec FluentValidation
Pour cette première partie, on reste dans de l'utilisation classique de FluentValidation
(cf. doc officielle):
- Ajout du package
FluentValidation.AspNetCore
- Configuration de
FluentValidation
dans leStartup
de notre application aspnetcore - Définition des
Dtos
ainsi que desValidators
associés
Une fois tout ça mis en place, il suffit de créer un nouvel endpoint utilisant un de nos Dtos
pour qu'il soit validé automatiquement par FluentValidation
et empêche toute saisie incomplète.
Ajout d'un endpoint retournant toutes les validations de l'application
C'est ici la partie la plus intéressante (côté serveur) de la mise en place du système !
Dans les grandes lignes, la mise en place se place comme suit :
- Ajout d'un endpoint dans un nouveau controller appelé
ValidationController
- Cet endpoint va ensuite appeler l'interface du service de description des validators, appelé sobrement
IValidationDescriptorService
- Durant la configuration de ce service dans le fichier
Startup.cs
, on prendra soin de lui passer l'Assembly
contenant les validators pour permettre de les récupérer par réflexion. - Toute la logique de transformation des validateurs de FluentValidation en
Dtos
va se situer dans leValidationDescriptorService
. Il se charge de retourner unDictionary<string, Dictionary<string, List<PropertyValidatorInfo>>>
, les clés du premierDictionary
correspondant au nom duDto
validé, et les clés du secondDictionary
au nom des propriétés soumises à des règles de validation du précédentDto
.- L'ensemble des validateurs de FluentValidation sont récupérés dans le
constructeur
- Puis la méthode
GetValidationDescriptors
commence la construction du premierDictionary
avec comme clé les noms desDto
validés - Elle appelle ensuite la méthode
GetPropertyValidationDescriptors
pour récupérer un secondDictionary
avec comme clé les noms des propriétés validés de chaqueDto
- Puis enfin c'est la méthode
GetPropertyValidatorInfo
qui est appelée pour constituer notreDto
PropertyValidatorInfo
- L'ensemble des validateurs de FluentValidation sont récupérés dans le
En conclusion
Et voilà, après avoir mis en place ce système, nous disposons d'un endpoint nous retournant la description de chaque validation appliquée côté API. Il ne nous reste "plus" qu'à récupérer ces validations et à les interpréter côté Client
, mais ce sera le sujet du prochain article, avec une implémentation en React
En attendant, j'espère que cet article aura pu vous donner des idées. Dans tous les cas, n'hésitez pas à me contacter sur Twitter @vivienfabing ou en commentaire, et que le code soit avec vous !
Commentaires