Validation avec l'interface IErrorDataInfo

Nico-pyright(c) (Traduction)

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.

- Titre : Validation avec l'interface IErrorDataInfo

- Auteur : Nico-pyright(c) (Traduction)

- Parution : 20 avril 2009

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2009 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Traduction

- Validation avec l'interface IErrorDataInfo

- Préambule

- Le contrôleur de classe

- Creation d'une class partielle

- Ajouter les méthodes partielles OnChanging et OnChanged

- Implémenter l'interface IDataErrorInfo

- Conclusion

Traduction

Cet article est la traduction la plus fidèle possible de l'article original : Validating with the IErrorDataInfo Interface

Validation avec l'interface IErrorDataInfo

Le but de ce tutoriel est d'expliquer une approche pour effectuer des validations dans une application ASP.NET MVC. Vous apprendrez comment empêcher quelqu'un de soumettre un formulaire HTML sans avoir fourni de valeurs à des champs obligatoire du formulaire. Dans ce tutoriel, vous apprendrez comment effectuer la validation à l'aide de l'interface IErrorDataInfo.

Préambule

Dans ce tutoriel, je vais utiliser la base de données MoviesDB et la table Movies. Cette table est composée des colonnes suivantes :

Nom de la colonne

Type de données

Null autorisé

Id

Int

Faux

Title

Nvarchar(100)

Faux

Director

Nvarchar(100)

Faux

DateReleased

DateTime

Faux

Dans ce tutoriel, j'ai utilisé l'Entity Framework de Microsoft pour générer les classes de mon modèle de base de données. La classe Movie générée par L'Entity Framework est affichée figure 1.

Figure 01 : L'entité Movie

Pour en savoir plus sur l'utilisation de l'Entity Framework pour générer votre modèle de base de données, allez voir mon tutoriel intitulé Créer des classes avec l'Entity Framework.

Le contrôleur de classe

Nous utilisons le contrôleur Home pour lister les films et en créer de nouveaux. Le code de cette classe est contenue dans le Listing 1.

Listing 1 – Controllers\HomeController.cs

using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
private MoviesDBEntities _db = new MoviesDBEntities();

public ActionResult Index()
{
return View(_db.MovieSet.ToList());
}

public ActionResult Create()
{
return View();
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "Id")] Movie movieToCreate)
{
// Validation
if (!ModelState.IsValid)
return View();

// Ajout à la base de données
try
{
_db.AddToMovieSet(movieToCreate);
_db.SaveChanges();

return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}

La classe du contrôleur Home du listing 1 contient deux actions Create(). La première action affiche le formulaire HTML pour la création d'un nouveau film. La deuxième action Create() effectue l'insertion 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 soumis au serveur.

Notez que la seconde action Create() contient les lignes de code suivantes :

// Validation
if (!ModelState.IsValid)
return View();

La propriété IsValid renvoie false quand il ya une erreur de validation. Dans ce cas, la vue Create qui contient le formulaire HTML pour créer un film est affichée à nouveau.

Creation d'une class partielle

La classe Movie est générée par l'Entity Framework. Vous pouvez voir le code de la classe Movie si vous développez l'arborescence du fichier MoviesDBModel.edmx dans la fenêtre de l'explorateur de solutions et si vous ouvrez le fichier MoviesDBModel.Designer.cs dans l'éditeur de code (voir Figure 2).

Figure 02 : Le code de l'entité Movie

La classe Movie est une classe partielle. Cela signifie que nous pouvons ajouter une autre classe partielle avec le même nom afin d'étendre les fonctionnalités de la classe Movie. Nous allons ajouter notre logique de validation à cette nouvelle classe partielle.

Ajoutez la classe du listing 2 au dossier Models.

Listing 2 – Models\Movie.cs

using System.Collections.Generic;
using System.ComponentModel;

namespace MvcApplication1.Models
{

public partial class Movie
{

}
}

Notez que la classe du Listing 2 comprend le mot clé partial. Toutes les méthodes ou les propriétés que vous ajoutez à cette classe feront partie de la classe Movie générée par l'Entity Framework.

Ajouter les méthodes partielles OnChanging et OnChanged

Lorsque l'Entity Framework génère une classe entité, l'Entity Framework ajoute automatiquement des méthodes partielles à la classe. L'Entity Framework génère des méthodes partielles OnChanging et OnChanged correspondant à chaque propriété de la classe.

Dans le cas de la classe Movie, l'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 qiue la propriété correspondante soit modifiée. La méthode OnChanged est appelée juste après que la propriété soit modifiée.

Vous pouvez tirer avantage de ces méthodes partielles pour ajouter la logique de validation à la classe Movie. La classe Movie mise à jour dans le listing 3 vérifie que les propriétés Title et Director sont affectées à des valeurs non vides.

Une méthode partielle est une méthode définie dans une classe que vous n'êtes pas obligé d'implémenter. Si vous n'implémentez pas une méthode partielle alors le compilateur supprime la signature de la méthode et tous les appels à la méthode afin qu'il n'y ait pas de coût d'exécution associé à la méthode partielle. Dans l'éditeur de code de Visual Studio, vous pouvez ajouter une méthode partielle en tapant le mot-clé partial suivi d'un espace pour afficher une liste des méthodes partielles à impélémenter.

Listing 3 – Models\Movie.cs

using System.Collections.Generic;
using System.ComponentModel;

namespace MvcApplication1.Models
{
public partial class Movie : IDataErrorInfo
{
private Dictionary<string, string> _errors = new Dictionary<string, string>();

partial void OnTitleChanging(string value)
{
if (value.Trim().Length == 0)
_errors.Add("Title", "Title is required.");
}

partial void OnDirectorChanging(string value)
{
if (value.Trim().Length == 0)
_errors.Add("Director", "Director is required.");
}
}
}

Par exemple, si vous essayez d'affecter une chaîne vide à la propriété Title, alors un message d'erreur est ajouté à un dictionnaire nommé _errors.

A ce stade, rien ne se produit encore lorsque vous affectez une chaîne vide à la propriété Title et une erreur est ajoutée au membre privé _errors. Nous avons besoin d'implémenter l'interface IDataErrorInfo afin d'exposer ces erreurs de validation au framework ASP.NET MVC.

Implémenter l'interface IDataErrorInfo

L'interface IDataErrorInfo fait partie du framework. NET depuis la première version. Cette interface est une interface très simple:

public interface IDataErrorInfo
{
string this[string columnName] { get; }

string Error { get; }
}

Si une classe implémente l'interface IDataErrorInfo, le framework ASP.NET MVC va utiliser cette interface lors de la création d'une instance de la classe. Par exemple, l'action Create() du contrôleur Home accepte une instance de la classe Movie :

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "Id")] Movie movieToCreate)
{
// Validation
if (!ModelState.IsValid)
return View();

// Ajout à la base de données
try
{
_db.AddToMovieSet(movieToCreate);
_db.SaveChanges();

return RedirectToAction("Index");
}
catch
{
return View();
}
}

Le framework ASP.NET MVC crée l'instance de la classe Movie passée à l'action Create() en utilisant un modèle de laison (DefaultModelBinder). Le modèle de liaison est responsable de la création d'une instance de l'objet Movie en liant les champs du formulaire HTML à une instance de l'objet Movie.

Le DefaultModelBinder détecte si une classe implémente ou non l'interface IDataErrorInfo. Si une classe implémente cette interface alors le modèle de liaison invoque l'indexeur IDataErrorInfo.this pour chaque propriété de la classe. Si l'indexeur retourne un message d'erreur alors le modèle de liaison ajoute automatiquement ce message d'erreur au modèle d'état.

Le DefaultModelBinder vérifie aussi la propriété IDataErrorInfo.Error. Cette propriété a pour but de représenter des erreurs de validations qui ne sont pas associées à des propriétés de la classe. Par exemple, vous pourriez vouloir appliquer une règle de validation qui dépend des valeurs de plusieurs propriétés de la classe Movie. Dans ce cas, vous pourriez retourner une erreur de validation à partir de la propriété Error.

La classe Movie mise à jour dans le listing 4 implémente l'interface IDataErrorInfo.

Listing 4 – Models\Movie.cs (implements IDataErrorInfo)

using System.Collections.Generic;
using System.ComponentModel;

namespace MvcApplication1.Models
{
public partial class Movie : IDataErrorInfo
{
private Dictionary<string, string> _errors = new Dictionary<string, string>();

partial void OnTitleChanging(string value)
{
if (value.Trim().Length == 0)
_errors.Add("Title", "Title is required.");
}

partial void OnDirectorChanging(string value)
{
if (value.Trim().Length == 0)
_errors.Add("Director", "Director is required.");
}

#region IDataErrorInfo Members

public string Error
{
get
{
return string.Empty;
}
}

public string this[string columnName]
{
get
{
if (_errors.ContainsKey(columnName))
return _errors[columnName];
return string.Empty;
}
}

#endregion
}
}

Dans le listing 4, la propriété indexée vérifie la collection _errors pour voir si elle contient une clé qui correspond au nom de la propriété passee à l'indexeur. S'il n'y a pas d'erreur de validation associée à la propriété alors une chaîne vide est retournée.

Vous n'avez pas besoin de modifier le contrôleur Home pour utiliser la nouvelle classe Movie. La page affichée figure 3 illustre ce qui se passe lorsque aucune valeur n'est entrée pour les champs de formulaire Title ou Director.

Figure 03 : Un formulaire avec des valeurs manquantes

Notez que la valeur DateReleased est validée automatiquement. Parce que la propriété DateReleased n'accepte pas les valeurs NULL, le DefaultModelBinder génère une erreur de validation automatiquement pour cette propriété quand elle ne contient pas de valeur. Si vous souhaitez modifier le message d'erreur pour la propriété DateReleased, vous devez créer un modèle de liaison personnalisé.

Conclusion

Dans ce tutoriel, vous avez appris comment utiliser l'interface IDataErrorInfo pour générer des messages d'erreur de validation. Dans un premier temps, nous avons créé classe partielle Movie qui étend les fonctionnalités de la classe partielle Movie générée par l'Entity Framework. Ensuite, nous avons ajouté la 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 au framework ASP.NET MVC.