Validation avec l’interface IDataErrorInfo (VB)
par Stephen Walther
Stephen Walther vous montre comment afficher des messages d’erreur de validation personnalisés en implémentant l’interface IDataErrorInfo dans une classe de modèle.
L’objectif de ce tutoriel est d’expliquer une approche pour effectuer la validation dans une application ASP.NET MVC. Vous apprenez à empêcher une personne d’envoyer un formulaire HTML sans fournir de valeurs pour les champs de formulaire obligatoires. Dans ce tutoriel, vous allez apprendre à effectuer une validation à l’aide de l’interface IErrorDataInfo.
Hypothèses
Dans ce tutoriel, je vais utiliser la base de données MoviesDB et la table de base de données Movies. Cette table présente les colonnes suivantes :
Nom de la colonne | Type de données | Null autorisé |
---|---|---|
Id | Int | False |
Titre | Nvarchar(100) | False |
Directeur | Nvarchar(100) | False |
DateReleased | DateTime | False |
Dans ce tutoriel, j’utilise Microsoft Entity Framework pour générer mes classes de modèle de base de données. La classe Movie générée par Entity Framework s’affiche dans la figure 1.
Figure 01 : L’entité Movie (Cliquer pour afficher l’image en taille réelle)
Notes
Pour en savoir plus sur l’utilisation d’Entity Framework pour générer vos classes de modèle de base de données, consultez mon tutoriel intitulé Création de classes de modèle avec Entity Framework.
Classe controller
Nous utilisons le contrôleur d’accueil pour répertorier les films et créer de nouveaux films. Le code de cette classe est contenu dans la liste 1.
Listing 1 - Controllers\HomeController.vb
Public Class HomeController
Inherits Controller
Private _db As New MoviesDBEntities()
Public Function Index() As ActionResult
Return View(_db.MovieSet.ToList())
End Function
Public Function Create() As ActionResult
Return View()
End Function
<AcceptVerbs(HttpVerbs.Post)> _
Public Function Create(<Bind(Exclude := "Id")> ByVal movieToCreate As Movie) As ActionResult
' Validate
If (Not ModelState.IsValid) Then
Return View()
End If
' Add to database
Try
_db.AddToMovieSet(movieToCreate)
_db.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
End Class
La classe de contrôleur Home dans la liste 1 contient deux actions Create(). La première action affiche le formulaire HTML permettant de créer un film. La deuxième action Create() effectue l’insertion réelle du nouveau film dans la base de données. La deuxième action Create() est appelée lorsque le formulaire affiché par la première action Create() est envoyé au serveur.
Notez que la deuxième action Create() contient les lignes de code suivantes :
' Validate
If (Not ModelState.IsValid) Then
Return View()
End If
La propriété IsValid retourne false en cas d’erreur de validation. Dans ce cas, la vue Créer qui contient le formulaire HTML pour la création d’un film est réaffichée.
Création d’une classe partielle
La classe Movie est générée par Entity Framework. Vous pouvez voir le code de la classe Movie si vous développez le fichier MoviesDBModel.edmx dans la fenêtre Explorateur de solutions et ouvrez moviesDBModel.Designer. fichier vb dans l’éditeur de code (voir la figure 2).
Figure 02 : Code de l’entité Movie (Cliquer pour afficher l’image en taille réelle)
La classe Movie est une classe partielle. Cela signifie que nous pouvons ajouter une autre classe partielle portant le même nom pour étendre les fonctionnalités de la classe Movie. Nous allons ajouter notre logique de validation à la nouvelle classe partielle.
Ajoutez la classe dans la liste 2 au dossier Models.
Listing 2 - Models\Movie.vb
Public Partial Class Movie
End Class
Notez que la classe de la liste 2 inclut le modificateur partiel . Toutes les méthodes ou propriétés que vous ajoutez à cette classe font partie de la classe Movie générée par Entity Framework.
Ajout de méthodes partielles OnChanging et OnChanged
Quand Entity Framework génère une classe d’entité, Entity Framework ajoute automatiquement des méthodes partielles à la classe. Entity Framework génère des méthodes partielles OnChanging et OnChanged qui correspondent à chaque propriété de la classe .
Dans le cas de la classe Movie, Entity Framework crée les méthodes suivantes :
- OnIdChanging
- OnIdChanged
- OnTitleChanging
- OnTitleChanged
- OnDirectorChanging
- OnDirectorChanged
- OnDateReleasedChanging
- OnDateReleasedChanged
La méthode OnChanging est appelée juste avant la modification de la propriété correspondante. La méthode OnChanged est appelée juste après la modification de la propriété.
Vous pouvez tirer parti de ces méthodes partielles pour ajouter une logique de validation à la classe Movie. La classe de mise à jour Movie dans listing 3 vérifie que les propriétés Title et Director sont affectées à des valeurs non vides.
Notes
Une méthode partielle est une méthode définie dans une classe que vous n’avez pas besoin d’implémenter. Si vous n’implémentez pas de méthode partielle, le compilateur supprime la signature de la méthode et tous les appels à la méthode afin qu’il n’y ait aucun coût d’exécution associé à la méthode partielle. Dans l’éditeur Visual Studio Code, vous pouvez ajouter une méthode partielle en tapant le mot clé partiel suivi d’un espace pour afficher la liste des éléments partiels à implémenter.
Listing 3 - Models\Movie.vb
Imports System.ComponentModel
Partial Public Class Movie
Implements IDataErrorInfo
Private _errors As New Dictionary(Of String, String)()
Private Sub OnTitleChanging(ByVal value As String)
If value.Trim().Length = 0 Then
_errors.Add("Title", "Title is required.")
End If
End Sub
Private Sub OnDirectorChanging(ByVal value As String)
If value.Trim().Length = 0 Then
_errors.Add("Director", "Director is required.")
End If
End Sub
End Class
Par exemple, si vous tentez d’affecter une chaîne vide à la propriété Title, un message d’erreur est affecté à un dictionnaire nommé _errors.
À ce stade, rien ne se passe réellement lorsque vous affectez une chaîne vide à la propriété Title et qu’une erreur est ajoutée au champ _errors privé. Nous devons implémenter l’interface IDataErrorInfo pour exposer ces erreurs de validation à l’infrastructure MVC ASP.NET.
Implémentation de l’interface IDataErrorInfo
L’interface IDataErrorInfo fait partie du .NET Framework depuis la première version. Cette interface est très simple :
Public Interface IDataErrorInfo
Default ReadOnly Property Item(ByVal columnName As String) As String
ReadOnly Property [Error]() As String
End Interface
Si une classe implémente l’interface IDataErrorInfo, l’infrastructure MVC ASP.NET utilise cette interface lors de la création d’un instance de la classe. Par exemple, l’action Create() du contrôleur d’accueil accepte une instance de la classe Movie :
<AcceptVerbs(HttpVerbs.Post)> _
Public Function Create(<Bind(Exclude := "Id")> ByVal movieToCreate As Movie) As ActionResult
' Validate
If (Not ModelState.IsValid) Then
Return View()
End If
' Add to database
Try
_db.AddToMovieSet(movieToCreate)
_db.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
L’infrastructure MVC ASP.NET crée la instance du film passée à l’action Create() à l’aide d’un classeur de modèles (DefaultModelBinder). Le classeur de modèles est chargé de créer une instance de l’objet Movie en liant les champs de formulaire HTML à un instance de l’objet Movie.
DefaultModelBinder détecte si une classe implémente ou non l’interface IDataErrorInfo. Si une classe implémente cette interface, le classeur de modèles appelle l’indexeur IDataErrorInfo.this pour chaque propriété de la classe . Si l’indexeur retourne un message d’erreur, le classeur de modèles ajoute automatiquement ce message d’erreur à l’état du modèle.
DefaultModelBinder vérifie également la propriété IDataErrorInfo.Error. Cette propriété est destinée à représenter les erreurs de validation non spécifiques à la propriété associées à la classe . Par exemple, vous pouvez appliquer une règle de validation qui dépend des valeurs de plusieurs propriétés de la classe Movie. Dans ce cas, vous renvoyez une erreur de validation à partir de la propriété Error.
La classe Movie mise à jour dans listing 4 implémente l’interface IDataErrorInfo.
Listing 4 - Models\Movie.vb (implémente IDataErrorInfo)
Imports System.ComponentModel
Partial Public Class Movie
Implements IDataErrorInfo
Private _errors As New Dictionary(Of String, String)()
Private Sub OnTitleChanging(ByVal value As String)
If value.Trim().Length = 0 Then
_errors.Add("Title", "Title is required.")
End If
End Sub
Private Sub OnDirectorChanging(ByVal value As String)
If value.Trim().Length = 0 Then
_errors.Add("Director", "Director is required.")
End If
End Sub
#Region "IDataErrorInfo Members"
Public ReadOnly Property [Error]() As String Implements IDataErrorInfo.Error
Get
Return String.Empty
End Get
End Property
Default Public ReadOnly Property Item(ByVal columnName As String) As String Implements IDataErrorInfo.Item
Get
If _errors.ContainsKey(columnName) Then
Return _errors(columnName)
End If
Return String.Empty
End Get
End Property
#End Region
End Class
Dans la liste 4, la propriété de l’indexeur vérifie la collection _errors pour voir si elle contient une clé qui correspond au nom de propriété transmis à l’indexeur. Si aucune erreur de validation n’est associée à la propriété, une chaîne vide est retournée.
Vous n’avez pas besoin de modifier le contrôleur Home de quelque manière que ce soit pour utiliser la classe Movie modifiée. La page affichée dans la figure 3 illustre ce qui se passe quand aucune valeur n’est entrée pour les champs Titre ou Formulaire Directeur.
Figure 03 : Formulaire avec des valeurs manquantes (Cliquer pour afficher l’image en taille réelle)
Notez que la valeur DateReleased est validée automatiquement. Étant donné que la propriété DateReleased n’accepte pas les valeurs NULL, DefaultModelBinder génère automatiquement une erreur de validation pour cette propriété lorsqu’elle n’a pas de valeur. Si vous souhaitez modifier le message d’erreur pour la propriété DateReleased, vous devez créer un classeur de modèles personnalisé.
Résumé
Dans ce tutoriel, vous avez appris à utiliser l’interface IDataErrorInfo pour générer des messages d’erreur de validation. Tout d’abord, nous avons créé une classe Movie partielle qui étend les fonctionnalités de la classe Movie partielle générée par Entity Framework. Ensuite, nous avons ajouté une logique de validation aux méthodes partielles OnTitleChanging() et OnDirectorChanging() de la classe Movie. Enfin, nous avons implémenté l’interface IDataErrorInfo afin d’exposer ces messages de validation à l’infrastructure MVC ASP.NET.