S’assurer que nos données sont correctes avant de faire des opérations plus complexes se basant sur elles est primordial. Nous allons voir comment on peut déléguer cette validation à des objets dont c’est la spécialité.
Ajouter des contraintes aux entités
Lorsqu’on a des données qui sont fournies par l’utilisateur, il faut toujours appliquer le principe du Filter Input Escape Output, autrement dit "filtre ce qu’on te donne, adapte ce que tu envoies".
Nous avons pu, lors des précédents chapitres utiliser le moteur de templating pour adapter proprement le HTML. De même nous avons utilisé certains attributs pour forcer le système à valider nos entrées.
Ces attributs ont pour point commun de dériver de ValidationAttribute
. Lorsque le modèle est construit par ASP.NET grâce aux entrées utilisateurs, le système va générer un objet ModelState
qui va dès lors prendre en compte chacun des attributs, et appeler leur méthode IsValid
. Dans le cas où la méthode retournerait false
, la propriété IsValid
de ModelState
passe à false
et il commence à remplir la liste des erreurs que vous pourrez afficher dans votre template.
Si vous désirez créer votre propre attribut pour valider un modèle, il suffit simplement de suivre ce modèle :
Notons que dans certains cas vous désirerez obtenir plus d’information afin de gérer la validation. Il faudra alors faire deux choses :
- plutôt que de surcharger
IsValid(object value)
, il faudra surchargerIsValid(object value, ValidationContext context)
. Le second paramètre contient pas mal d’informations qui peuvent être utiles. - il faudra surcharger la propriété
RequiresValidationContext
et la passer àtrue
dans le constructeur.
Bonnes pratiques
- C’est à
Required
de vérifier qu’un champ n’est pas vide, le retour par défaut, en cas de champ vide pour un validateur personnalisé, doit donc êtretrue
. - Corrolaire de la première bonne pratique, lors de la conversion de la valeur en le type désiré, utilisé le cast
as XXX
qui retourneranull
en cas d’échec.
Un peu plus loin : les MetaType
Le concept de méta données
Nous l’avons vu, la validation des données est une chose très facile à mettre en place dans ASP.NET.
Néanmoins, vous arriverez souvent à un point où vous aurez plusieurs entités qui se ressemblent ou qui partagent certains attributs. Cela peut se trouver dans vos view-model mais aussi plus globalement dans tous les modèles de votre application.
Imaginons que vous permettiez à vos visiteur de vous envoyer un email via un formulaire de contact.
Ce dernier serait alors composé d’un sujet, et d’un texte.
N’est-ce pas aussi à cela que peut ressembler un commentaire de votre blog? Du moins le commentaire de votre blog aura-t-il un point commun avec le formulaire de contact : il contient un texte.
Le problème c’est que dans un cas comme dans l’autre, vous aimeriez que le texte subissent certaines validations, comme par exemple une validation Anti Spam.
Une idée assez simple serait alors de dire à tous les modèles d’hériter d’un modèle qui possède un texte et les attributs idoines.
Malheureusement, cela pose deux problèmes:
- cela "bloque" votre héritage : en effet en C# on ne peut pas hériter de deux classes en même temps;
- cela n’a pas forcément de sens : certes on pourrait simplement dire que notre classe de basse s’appelle
ElementWithAntiSpamText
mais avouons que c’est un peu dommage de créer une classe qui offrirait si peu de fonctionnalités de base qu’on doit créer des classes autour qui ajouteront un vrai sens métier.
Une autre idée serait d’utiliser une fonctionnalité avancée de C# : les méta type. Comme il ne s’agit pas d’une fonctionnalité propre à ASP.NET, je ne vous détaillerai pas le mécanisme complet derrière ce concept, mais voyez le principe de méta type comme la possibilité de définir une base commune à plusieurs sous-type mais sans donner le sens et les contraintes liés à l’héritage. Vous allez offrir une description de votre type de base (le méta type) et le compilateur se chargera d’incorporer cette description dans toutes vos classes réelles.
Vous pouvez maintenant être assurés de la qualité des données que vous manipulez.