Partager via


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.

L’entité Movie

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).

Code de l’entité Movie

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.

Création automatique de méthodes d’action

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.