Partie 9, ajouter la validation à une application MVC ASP.NET Core

Remarque

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.

Important

Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.

Pour la version actuelle, consultez la version .NET 8 de cet article.

Par Rick Anderson

Dans cette section :

  • Une logique de validation est ajoutée au modèle Movie.
  • Vous vous assurez que les règles de validation sont appliquées chaque fois qu’un utilisateur crée ou modifie un film.

Ne vous répétez pas

L’un des principes de conception de MVC est « Ne vous répétez pas » (désigné par l’acronyme DRY, Don’t Repeat Yourself). ASP.NET Core MVC vous encourage à spécifier les fonctionnalités ou les comportements une seule fois, puis à utiliser la réflexion partout dans une application. Cela réduit la quantité de code à écrire, et rend le code que vous écrivez moins susceptible aux erreurs et plus facile à tester et à gérer.

La prise en charge de la validation fournie par MVC et Entity Framework Core Code First est un bon exemple du principe DRY en action. Vous pouvez spécifier de façon déclarative des règles de validation à un seul emplacement (dans la classe de modèle), et les règles sont appliquées partout dans l’application.

Ajouter des règles de validation au modèle de film

L’espace de noms DataAnnotations fournit un ensemble d’attributs de validation intégrés qui sont appliqués de façon déclarative à une classe ou à une propriété. DataAnnotations contient également des attributs de mise en forme, comme DataType, qui aident à effectuer la mise en forme et ne fournissent aucune validation.

Mettez à jour la classe Movie pour tirer parti des attributs de validation intégrés Required, StringLength, RegularExpression, Range et de l’attribut de mise en forme DataType.

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models;

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    [Required]
    public string? Title { get; set; }

    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Range(1, 100)]
    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }    

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
    [Required]
    [StringLength(30)]
    public string? Genre { get; set; }
    
    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
    [StringLength(5)]
    [Required]
    public string? Rating { get; set; }
}

Les attributs de validation spécifient le comportement que vous souhaitez appliquer sur les propriétés du modèle sur lesquels ils sont appliqués :

  • Les attributs Required et MinimumLength indiquent qu’une propriété doit avoir une valeur, mais rien n’empêche un utilisateur d’entrer un espace pour satisfaire à cette validation.

  • L’attribut RegularExpression sert à limiter les caractères pouvant être entrés. Dans le code précédent, « Genre » :

    • Doit utiliser seulement des lettres.
    • La première lettre doit être une majuscule. Les espaces blancs sont autorisés tandis que les nombres et les caractères spéciaux ne sont pas autorisés.
  • L’expression RegularExpression « Rating » :

    • Nécessite que le premier caractère soit une lettre majuscule.
    • Autorise les caractères spéciaux et les chiffres aux emplacements qui suivent. « PG-13 » est valide pour une évaluation, mais échoue pour un « Genre ».
  • L’attribut Range limite une valeur à une plage spécifiée.

  • L’attribut StringLength vous permet de définir la longueur maximale d’une propriété de chaîne, et éventuellement sa longueur minimale.

  • Les types valeur (tels que decimal, int, float et DateTime) sont obligatoires par nature et n’ont pas besoin de l’attribut [Required].

L’application automatique des règles de validation par ASP.NET Core permet d’accroître la fiabilité de votre application. Cela garantit également que vous n’oublierez pas de valider un élément et que vous n’autoriserez pas par inadvertance l’insertion de données incorrectes dans la base de données.

Interface utilisateur des erreurs de validation

Exécutez l’application et accédez au contrôleur Movies.

Sélectionnez le lien Créer nouveau pour ajouter un nouveau film. Remplissez le formulaire avec des valeurs non valides. Dès que la validation côté client jQuery détecte l’erreur, elle affiche un message d’erreur.

Formulaire d’affichage de film avec plusieurs erreurs de validation côté client jQuery

Notes

Vous ne pourrez peut-être pas entrer de virgules décimales dans les champs décimaux. Pour prendre en charge la validation jQuery pour les paramètres régionaux autres que l’anglais qui utilisent une virgule (« , ») comme décimale et des formats de date autres que l’anglais des États-Unis, vous devez effectuer des étapes pour localiser votre application. Consultez ce commentaire GitHub 4076 pour savoir comment ajouter une virgule décimale.

Notez que le formulaire a affiché automatiquement un message d’erreur de validation approprié dans chaque champ contenant une valeur non valide. Les erreurs sont appliquées à la fois côté client (à l’aide de JavaScript et jQuery) et côté serveur (au cas où un utilisateur aurait désactivé JavaScript).

L’un des principaux avantages est que vous n’avez pas eu à changer une seule ligne de code dans la classe MoviesController ou dans la vue Create.cshtml pour activer cette interface utilisateur de validation. Le contrôleur et les vues créées précédemment dans ce didacticiel ont détecté les règles de validation que vous avez spécifiées à l’aide des attributs de validation sur les propriétés de la classe de modèle Movie. Testez la validation à l’aide de la méthode d’action Edit. La même validation est appliquée.

Les données de formulaire ne sont pas envoyées au serveur tant qu’il y a des erreurs de validation côté client. Vous pouvez vérifier cela en plaçant un point d’arrêt dans la méthode HTTP Post, en utilisant l’outil Fiddler ou à l’aide des Outils de développement F12.

Fonctionnement de la validation

Vous vous demandez peut-être comment l’interface utilisateur de validation a été générée sans aucune mise à jour du code dans le contrôleur ou dans les vues. Le code suivant montre les deux méthodes Create.

// GET: Movies/Create
public IActionResult Create()
{
    return View();
}

// POST: Movies/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (ModelState.IsValid)
    {
        _context.Add(movie);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

La première méthode d’action (HTTP GET) Create affiche le formulaire de création initial. La deuxième version ([HttpPost]) gère la publication de formulaire. La seconde méthode Create (la version [HttpPost]) appelle ModelState.IsValid pour vérifier si le film a des erreurs de validation. L’appel de cette méthode évalue tous les attributs de validation qui ont été appliqués à l’objet. Si l’objet comporte des erreurs de validation, la méthode Create réaffiche le formulaire. S’il n’y a pas d’erreur, la méthode enregistre le nouveau film dans la base de données. Dans notre exemple de film, le formulaire n’est pas publié sur le serveur quand des erreurs de validation sont détectées côté client ; la seconde méthode Create n’est jamais appelée quand il y a des erreurs de validation côté client. Si vous désactivez JavaScript dans votre navigateur, la validation client est désactivée et vous pouvez tester la méthode Create HTTP POST ModelState.IsValid pour détecter les erreurs de validation.

Vous pouvez définir un point d’arrêt dans la méthode [HttpPost] Create et vérifier que la méthode n’est jamais appelée. La validation côté client n’enverra pas les données du formulaire quand des erreurs de validation seront détectées. Si vous désactivez JavaScript dans votre navigateur et que vous envoyez ensuite le formulaire avec des erreurs, le point d’arrêt sera atteint. Vous bénéficiez toujours d’une validation complète sans JavaScript.

L’illustration suivante montre comment désactiver JavaScript dans le navigateur Firefox.

Firefox : dans Options, sous l’onglet Contenu, décochez la case Activer Javascript.

L’illustration suivante montre comment désactiver JavaScript dans le navigateur Chrome.

Google Chrome : dans Paramètres de contenu, dans la section Javascript, sélectionnez Interdire à tous les sites d’exécuter JavaScript.

Après la désactivation de JavaScript, publiez les données non valides et parcourez le débogueur.

Pendant le débogage d’une publication de données non valides, Intellisense sur ModelState.IsValid indique que la valeur est false.

Une partie du modèle d’affichage Create.cshtml est indiquée dans le balisage suivant :

<h4>Movie</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>

            @*Markup removed for brevity.*@

Le balisage précédent est utilisé par les méthodes d’action pour afficher le formulaire initial et pour le réafficher en cas d’erreur.

Le Tag Helper Input utilise les attributs DataAnnotations et produit les attributs HTML nécessaires à la validation jQuery côté client. Le Tag Helper Validation affiche les erreurs de validation. Pour plus d’informations, consultez Validation.

Le grand avantage de cette approche est que ni le contrôleur ni le modèle de vue Create ne savent rien des règles de validation appliquées ou des messages d’erreur affichés. Les règles de validation et les chaînes d’erreur sont spécifiées uniquement dans la classe Movie. Ces mêmes règles de validation sont automatiquement appliquées à la vue Edit et à tous les autres modèles de vues que vous pouvez créer et qui modifient votre modèle.

Quand vous devez changer la logique de validation, vous pouvez le faire à un seul endroit en ajoutant des attributs de validation au modèle (dans cet exemple, la classe Movie). Vous n’aurez pas à vous soucier des différentes parties de l’application qui pourraient être incohérentes avec la façon dont les règles sont appliquées. Toute la logique de validation sera définie à un seul emplacement et utilisée partout. Le code est ainsi très propre, facile à mettre à jour et évolutif. Et cela signifie que vous respecterez entièrement le principe DRY.

Utilisation d’attributs DataType

Ouvrez le fichier Movie.cs et examinez la classe Movie. L’espace de noms System.ComponentModel.DataAnnotations fournit des attributs de mise en forme en plus de l’ensemble intégré d’attributs de validation. Nous avons déjà appliqué une valeur d’énumération DataType aux champs de date de sortie et de prix. Le code suivant illustre les propriétés ReleaseDate et Price avec l’attribut DataType approprié.

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }    

Les attributs DataType fournissent uniquement des indices permettant au moteur de vue de mettre en forme les données (et fournissent des éléments/attributs tels que <a> pour les URL et <a href="mailto:EmailAddress.com"> pour l’e-mail). Vous pouvez utiliser l’attribut RegularExpression pour valider le format des données. L’attribut DataType sert à spécifier un type de données qui est plus spécifique que le type intrinsèque de la base de données ; il ne s’agit pas d’un attribut de validation. Dans le cas présent, nous voulons uniquement effectuer le suivi de la date, et non de l’heure. L’énumération DataType fournit de nombreux types de données, telles que Date, Time, PhoneNumber, Currency ou EmailAddress. L’attribut DataType peut également permettre à l’application de fournir automatiquement des fonctionnalités propres au type. Par exemple, vous pouvez créer un lien mailto: pour DataType.EmailAddress, et vous pouvez fournir un sélecteur de date pour DataType.Date dans les navigateurs qui prennent en charge HTML5. Les attributs DataType émettent des attributs HTML 5 data- compréhensibles par les navigateurs HTML 5. Les attributs DataType ne fournissent aucune validation.

DataType.Date ne spécifie pas le format de la date qui s’affiche. Par défaut, le champ de données est affiché conformément aux formats par défaut basés sur le CultureInfo du serveur.

L’attribut DisplayFormat est utilisé pour spécifier explicitement le format de date :

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

Le paramètre ApplyFormatInEditMode indique que la mise en forme doit également être appliquée quand la valeur est affichée dans une zone de texte à des fins de modification. (Ceci peut ne pas être souhaitable pour certains champs ; par exemple, pour les valeurs monétaires, vous ne souhaiterez sans doute pas que le symbole monétaire figure dans la zone de texte.)

Vous pouvez utiliser l’attribut DisplayFormat par lui-même, mais il est généralement préférable d’utiliser l’attribut DataType. L’attribut DataType donne la sémantique des données, plutôt que de décrire comment effectuer le rendu sur un écran, et il offre les avantages suivants dont vous ne bénéficiez pas avec DisplayFormat :

  • Le navigateur peut activer des fonctionnalités HTML5 (par exemple pour afficher un contrôle de calendrier, le symbole monétaire correspondant aux paramètres régionaux, des liens de messagerie, etc.).

  • Par défaut, le navigateur affiche les données à l’aide du format correspondant à vos paramètres régionaux.

  • L’attribut DataType peut permettre à MVC de choisir le modèle de champ correct pour afficher les données (DisplayFormat, utilisé par lui-même, utilise le modèle de chaîne).

Notes

La validation jQuery ne fonctionne pas avec l’attribut Range et DateTime. Par exemple, le code suivant affiche toujours une erreur de validation côté client, même quand la date se trouve dans la plage spécifiée :

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

Vous devez désactiver la validation de date jQuery pour utiliser l’attribut Range avec DateTime. Il n’est généralement pas recommandé de compiler des dates dures dans vos modèles. Par conséquent, l’utilisation de l’attribut Range et de DateTime est déconseillée.

Le code suivant illustre la combinaison d’attributs sur une seule ligne :

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models;

public class Movie
{
    public int Id { get; set; }
    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; }
    [Display(Name = "Release Date"), DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }
    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
    public string Genre { get; set; }
    [Range(1, 100), DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }
    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
    public string Rating { get; set; }
}

Dans la partie suivante de la série, nous examinons l’application et nous apportons des améliorations aux méthodes Details et Delete générées automatiquement.

Ressources supplémentaires

Dans cette section :

  • Une logique de validation est ajoutée au modèle Movie.
  • Vous vous assurez que les règles de validation sont appliquées chaque fois qu’un utilisateur crée ou modifie un film.

Ne vous répétez pas

L’un des principes de conception de MVC est « Ne vous répétez pas » (désigné par l’acronyme DRY, Don’t Repeat Yourself). ASP.NET Core MVC vous encourage à spécifier les fonctionnalités ou les comportements une seule fois, puis à utiliser la réflexion partout dans une application. Cela réduit la quantité de code à écrire, et rend le code que vous écrivez moins susceptible aux erreurs et plus facile à tester et à gérer.

La prise en charge de la validation fournie par MVC et Entity Framework Core Code First est un bon exemple du principe DRY en action. Vous pouvez spécifier de façon déclarative des règles de validation à un seul emplacement (dans la classe de modèle), et les règles sont appliquées partout dans l’application.

Ajouter des règles de validation au modèle de film

L’espace de noms DataAnnotations fournit un ensemble d’attributs de validation intégrés qui sont appliqués de façon déclarative à une classe ou à une propriété. DataAnnotations contient également des attributs de mise en forme, comme DataType, qui aident à effectuer la mise en forme et ne fournissent aucune validation.

Mettez à jour la classe Movie pour tirer parti des attributs de validation intégrés Required, StringLength, RegularExpression, Range et de l’attribut de mise en forme DataType.

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models;

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    [Required]
    public string? Title { get; set; }

    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Range(1, 100)]
    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }    

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
    [Required]
    [StringLength(30)]
    public string? Genre { get; set; }
    
    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
    [StringLength(5)]
    [Required]
    public string? Rating { get; set; }
}

Les attributs de validation spécifient le comportement que vous souhaitez appliquer sur les propriétés du modèle sur lesquels ils sont appliqués :

  • Les attributs Required et MinimumLength indiquent qu’une propriété doit avoir une valeur, mais rien n’empêche un utilisateur d’entrer un espace pour satisfaire à cette validation.

  • L’attribut RegularExpression sert à limiter les caractères pouvant être entrés. Dans le code précédent, « Genre » :

    • Doit utiliser seulement des lettres.
    • La première lettre doit être une majuscule. Les espaces blancs sont autorisés tandis que les nombres et les caractères spéciaux ne sont pas autorisés.
  • L’expression RegularExpression « Rating » :

    • Nécessite que le premier caractère soit une lettre majuscule.
    • Autorise les caractères spéciaux et les chiffres aux emplacements qui suivent. « PG-13 » est valide pour une évaluation, mais échoue pour un « Genre ».
  • L’attribut Range limite une valeur à une plage spécifiée.

  • L’attribut StringLength vous permet de définir la longueur maximale d’une propriété de chaîne, et éventuellement sa longueur minimale.

  • Les types valeur (tels que decimal, int, float et DateTime) sont obligatoires par nature et n’ont pas besoin de l’attribut [Required].

L’application automatique des règles de validation par ASP.NET Core permet d’accroître la fiabilité de votre application. Cela garantit également que vous n’oublierez pas de valider un élément et que vous n’autoriserez pas par inadvertance l’insertion de données incorrectes dans la base de données.

Interface utilisateur des erreurs de validation

Exécutez l’application et accédez au contrôleur Movies.

Sélectionnez le lien Créer nouveau pour ajouter un nouveau film. Remplissez le formulaire avec des valeurs non valides. Dès que la validation côté client jQuery détecte l’erreur, elle affiche un message d’erreur.

Formulaire d’affichage de film avec plusieurs erreurs de validation côté client jQuery

Notes

Vous ne pourrez peut-être pas entrer de virgules décimales dans les champs décimaux. Pour prendre en charge la validation jQuery pour les paramètres régionaux autres que l’anglais qui utilisent une virgule (« , ») comme décimale et des formats de date autres que l’anglais des États-Unis, vous devez effectuer des étapes pour localiser votre application. Consultez ce commentaire GitHub 4076 pour savoir comment ajouter une virgule décimale.

Notez que le formulaire a affiché automatiquement un message d’erreur de validation approprié dans chaque champ contenant une valeur non valide. Les erreurs sont appliquées à la fois côté client (à l’aide de JavaScript et jQuery) et côté serveur (au cas où un utilisateur aurait désactivé JavaScript).

L’un des principaux avantages est que vous n’avez pas eu à changer une seule ligne de code dans la classe MoviesController ou dans la vue Create.cshtml pour activer cette interface utilisateur de validation. Le contrôleur et les vues créées précédemment dans ce didacticiel ont détecté les règles de validation que vous avez spécifiées à l’aide des attributs de validation sur les propriétés de la classe de modèle Movie. Testez la validation à l’aide de la méthode d’action Edit. La même validation est appliquée.

Les données de formulaire ne sont pas envoyées au serveur tant qu’il y a des erreurs de validation côté client. Vous pouvez vérifier cela en plaçant un point d’arrêt dans la méthode HTTP Post, en utilisant l’outil Fiddler ou à l’aide des Outils de développement F12.

Fonctionnement de la validation

Vous vous demandez peut-être comment l’interface utilisateur de validation a été générée sans aucune mise à jour du code dans le contrôleur ou dans les vues. Le code suivant montre les deux méthodes Create.

// GET: Movies/Create
public IActionResult Create()
{
    return View();
}

// POST: Movies/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (ModelState.IsValid)
    {
        _context.Add(movie);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

La première méthode d’action (HTTP GET) Create affiche le formulaire de création initial. La deuxième version ([HttpPost]) gère la publication de formulaire. La seconde méthode Create (la version [HttpPost]) appelle ModelState.IsValid pour vérifier si le film a des erreurs de validation. L’appel de cette méthode évalue tous les attributs de validation qui ont été appliqués à l’objet. Si l’objet comporte des erreurs de validation, la méthode Create réaffiche le formulaire. S’il n’y a pas d’erreur, la méthode enregistre le nouveau film dans la base de données. Dans notre exemple de film, le formulaire n’est pas publié sur le serveur quand des erreurs de validation sont détectées côté client ; la seconde méthode Create n’est jamais appelée quand il y a des erreurs de validation côté client. Si vous désactivez JavaScript dans votre navigateur, la validation client est désactivée et vous pouvez tester la méthode Create HTTP POST ModelState.IsValid pour détecter les erreurs de validation.

Vous pouvez définir un point d’arrêt dans la méthode [HttpPost] Create et vérifier que la méthode n’est jamais appelée. La validation côté client n’enverra pas les données du formulaire quand des erreurs de validation seront détectées. Si vous désactivez JavaScript dans votre navigateur et que vous envoyez ensuite le formulaire avec des erreurs, le point d’arrêt sera atteint. Vous bénéficiez toujours d’une validation complète sans JavaScript.

L’illustration suivante montre comment désactiver JavaScript dans le navigateur Firefox.

Firefox : dans Options, sous l’onglet Contenu, décochez la case Activer Javascript.

L’illustration suivante montre comment désactiver JavaScript dans le navigateur Chrome.

Google Chrome : dans Paramètres de contenu, dans la section Javascript, sélectionnez Interdire à tous les sites d’exécuter JavaScript.

Après la désactivation de JavaScript, publiez les données non valides et parcourez le débogueur.

Pendant le débogage d’une publication de données non valides, Intellisense sur ModelState.IsValid indique que la valeur est false.

Une partie du modèle d’affichage Create.cshtml est indiquée dans le balisage suivant :

<h4>Movie</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>

            @*Markup removed for brevity.*@

Le balisage précédent est utilisé par les méthodes d’action pour afficher le formulaire initial et pour le réafficher en cas d’erreur.

Le Tag Helper Input utilise les attributs DataAnnotations et produit les attributs HTML nécessaires à la validation jQuery côté client. Le Tag Helper Validation affiche les erreurs de validation. Pour plus d’informations, consultez Validation.

Le grand avantage de cette approche est que ni le contrôleur ni le modèle de vue Create ne savent rien des règles de validation appliquées ou des messages d’erreur affichés. Les règles de validation et les chaînes d’erreur sont spécifiées uniquement dans la classe Movie. Ces mêmes règles de validation sont automatiquement appliquées à la vue Edit et à tous les autres modèles de vues que vous pouvez créer et qui modifient votre modèle.

Quand vous devez changer la logique de validation, vous pouvez le faire à un seul endroit en ajoutant des attributs de validation au modèle (dans cet exemple, la classe Movie). Vous n’aurez pas à vous soucier des différentes parties de l’application qui pourraient être incohérentes avec la façon dont les règles sont appliquées. Toute la logique de validation sera définie à un seul emplacement et utilisée partout. Le code est ainsi très propre, facile à mettre à jour et évolutif. Et cela signifie que vous respecterez entièrement le principe DRY.

Utilisation d’attributs DataType

Ouvrez le fichier Movie.cs et examinez la classe Movie. L’espace de noms System.ComponentModel.DataAnnotations fournit des attributs de mise en forme en plus de l’ensemble intégré d’attributs de validation. Nous avons déjà appliqué une valeur d’énumération DataType aux champs de date de sortie et de prix. Le code suivant illustre les propriétés ReleaseDate et Price avec l’attribut DataType approprié.

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }    

Les attributs DataType fournissent uniquement des indices permettant au moteur de vue de mettre en forme les données (et fournissent des éléments/attributs tels que <a> pour les URL et <a href="mailto:EmailAddress.com"> pour l’e-mail). Vous pouvez utiliser l’attribut RegularExpression pour valider le format des données. L’attribut DataType sert à spécifier un type de données qui est plus spécifique que le type intrinsèque de la base de données ; il ne s’agit pas d’un attribut de validation. Dans le cas présent, nous voulons uniquement effectuer le suivi de la date, et non de l’heure. L’énumération DataType fournit de nombreux types de données, telles que Date, Time, PhoneNumber, Currency ou EmailAddress. L’attribut DataType peut également permettre à l’application de fournir automatiquement des fonctionnalités propres au type. Par exemple, vous pouvez créer un lien mailto: pour DataType.EmailAddress, et vous pouvez fournir un sélecteur de date pour DataType.Date dans les navigateurs qui prennent en charge HTML5. Les attributs DataType émettent des attributs HTML 5 data- compréhensibles par les navigateurs HTML 5. Les attributs DataType ne fournissent aucune validation.

DataType.Date ne spécifie pas le format de la date qui s’affiche. Par défaut, le champ de données est affiché conformément aux formats par défaut basés sur le CultureInfo du serveur.

L’attribut DisplayFormat est utilisé pour spécifier explicitement le format de date :

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

Le paramètre ApplyFormatInEditMode indique que la mise en forme doit également être appliquée quand la valeur est affichée dans une zone de texte à des fins de modification. (Ceci peut ne pas être souhaitable pour certains champs ; par exemple, pour les valeurs monétaires, vous ne souhaiterez sans doute pas que le symbole monétaire figure dans la zone de texte.)

Vous pouvez utiliser l’attribut DisplayFormat par lui-même, mais il est généralement préférable d’utiliser l’attribut DataType. L’attribut DataType donne la sémantique des données, plutôt que de décrire comment effectuer le rendu sur un écran, et il offre les avantages suivants dont vous ne bénéficiez pas avec DisplayFormat :

  • Le navigateur peut activer des fonctionnalités HTML5 (par exemple pour afficher un contrôle de calendrier, le symbole monétaire correspondant aux paramètres régionaux, des liens de messagerie, etc.).

  • Par défaut, le navigateur affiche les données à l’aide du format correspondant à vos paramètres régionaux.

  • L’attribut DataType peut permettre à MVC de choisir le modèle de champ correct pour afficher les données (DisplayFormat, utilisé par lui-même, utilise le modèle de chaîne).

Notes

La validation jQuery ne fonctionne pas avec l’attribut Range et DateTime. Par exemple, le code suivant affiche toujours une erreur de validation côté client, même quand la date se trouve dans la plage spécifiée :

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

Vous devez désactiver la validation de date jQuery pour utiliser l’attribut Range avec DateTime. Il n’est généralement pas recommandé de compiler des dates dures dans vos modèles. Par conséquent, l’utilisation de l’attribut Range et de DateTime est déconseillée.

Le code suivant illustre la combinaison d’attributs sur une seule ligne :

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models;

public class Movie
{
    public int Id { get; set; }
    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; }
    [Display(Name = "Release Date"), DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }
    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
    public string Genre { get; set; }
    [Range(1, 100), DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }
    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
    public string Rating { get; set; }
}

Dans la partie suivante de la série, nous examinons l’application et nous apportons des améliorations aux méthodes Details et Delete générées automatiquement.

Ressources supplémentaires

Dans cette section :

  • Une logique de validation est ajoutée au modèle Movie.
  • Vous vous assurez que les règles de validation sont appliquées chaque fois qu’un utilisateur crée ou modifie un film.

Ne vous répétez pas

L’un des principes de conception de MVC est « Ne vous répétez pas » (désigné par l’acronyme DRY, Don’t Repeat Yourself). ASP.NET Core MVC vous encourage à spécifier les fonctionnalités ou les comportements une seule fois, puis à utiliser la réflexion partout dans une application. Cela réduit la quantité de code à écrire, et rend le code que vous écrivez moins susceptible aux erreurs et plus facile à tester et à gérer.

La prise en charge de la validation fournie par MVC et Entity Framework Core Code First est un bon exemple du principe DRY en action. Vous pouvez spécifier de façon déclarative des règles de validation à un seul emplacement (dans la classe de modèle), et les règles sont appliquées partout dans l’application.

Ajouter des règles de validation au modèle de film

L’espace de noms DataAnnotations fournit un ensemble d’attributs de validation intégrés qui sont appliqués de façon déclarative à une classe ou à une propriété. DataAnnotations contient également des attributs de mise en forme, comme DataType, qui aident à effectuer la mise en forme et ne fournissent aucune validation.

Mettez à jour la classe Movie pour tirer parti des attributs de validation intégrés Required, StringLength, RegularExpression et Range.

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int Id { get; set; }

        [StringLength(60, MinimumLength = 3)]
        [Required]
        public string? Title { get; set; }

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [Range(1, 100)]
        [DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
        [Required]
        [StringLength(30)]
        public string? Genre { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
        [StringLength(5)]
        [Required]
        public string? Rating { get; set; }
    }
}

Les attributs de validation spécifient le comportement que vous souhaitez appliquer sur les propriétés du modèle sur lesquels ils sont appliqués :

  • Les attributs Required et MinimumLength indiquent qu’une propriété doit avoir une valeur, mais rien n’empêche un utilisateur d’entrer un espace pour satisfaire à cette validation.

  • L’attribut RegularExpression sert à limiter les caractères pouvant être entrés. Dans le code précédent, « Genre » :

    • Doit utiliser seulement des lettres.
    • La première lettre doit être une majuscule. Les espaces blancs sont autorisés tandis que les nombres et les caractères spéciaux ne sont pas autorisés.
  • L’expression RegularExpression « Rating » :

    • Nécessite que le premier caractère soit une lettre majuscule.
    • Autorise les caractères spéciaux et les chiffres aux emplacements qui suivent. « PG-13 » est valide pour une évaluation, mais échoue pour un « Genre ».
  • L’attribut Range limite une valeur à une plage spécifiée.

  • L’attribut StringLength vous permet de définir la longueur maximale d’une propriété de chaîne, et éventuellement sa longueur minimale.

  • Les types valeur (tels que decimal, int, float et DateTime) sont obligatoires par nature et n’ont pas besoin de l’attribut [Required].

L’application automatique des règles de validation par ASP.NET Core permet d’accroître la fiabilité de votre application. Cela garantit également que vous n’oublierez pas de valider un élément et que vous n’autoriserez pas par inadvertance l’insertion de données incorrectes dans la base de données.

Interface utilisateur des erreurs de validation

Exécutez l’application et accédez au contrôleur Movies.

Sélectionnez le lien Créer nouveau pour ajouter un nouveau film. Remplissez le formulaire avec des valeurs non valides. Dès que la validation côté client jQuery détecte l’erreur, elle affiche un message d’erreur.

Formulaire d’affichage de film avec plusieurs erreurs de validation côté client jQuery

Notes

Vous ne pourrez peut-être pas entrer de virgules décimales dans les champs décimaux. Pour prendre en charge la validation jQuery pour les paramètres régionaux autres que l’anglais qui utilisent une virgule (« , ») comme décimale et des formats de date autres que l’anglais des États-Unis, vous devez effectuer des étapes pour localiser votre application. Consultez ce commentaire GitHub 4076 pour savoir comment ajouter une virgule décimale.

Notez que le formulaire a affiché automatiquement un message d’erreur de validation approprié dans chaque champ contenant une valeur non valide. Les erreurs sont appliquées à la fois côté client (à l’aide de JavaScript et jQuery) et côté serveur (au cas où un utilisateur aurait désactivé JavaScript).

L’un des principaux avantages est que vous n’avez pas eu à changer une seule ligne de code dans la classe MoviesController ou dans la vue Create.cshtml pour activer cette interface utilisateur de validation. Le contrôleur et les vues créées précédemment dans ce didacticiel ont détecté les règles de validation que vous avez spécifiées à l’aide des attributs de validation sur les propriétés de la classe de modèle Movie. Testez la validation à l’aide de la méthode d’action Edit. La même validation est appliquée.

Les données de formulaire ne sont pas envoyées au serveur tant qu’il y a des erreurs de validation côté client. Vous pouvez vérifier cela en plaçant un point d’arrêt dans la méthode HTTP Post, en utilisant l’outil Fiddler ou à l’aide des Outils de développement F12.

Fonctionnement de la validation

Vous vous demandez peut-être comment l’interface utilisateur de validation a été générée sans aucune mise à jour du code dans le contrôleur ou dans les vues. Le code suivant montre les deux méthodes Create.

// GET: Movies/Create
public IActionResult Create()
{
    return View();
}

// POST: Movies/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Title,ReleaseDate,Genre,Price,Rating")] Movie movie)
{
    if (ModelState.IsValid)
    {
        _context.Add(movie);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}

La première méthode d’action (HTTP GET) Create affiche le formulaire de création initial. La deuxième version ([HttpPost]) gère la publication de formulaire. La seconde méthode Create (la version [HttpPost]) appelle ModelState.IsValid pour vérifier si le film a des erreurs de validation. L’appel de cette méthode évalue tous les attributs de validation qui ont été appliqués à l’objet. Si l’objet comporte des erreurs de validation, la méthode Create réaffiche le formulaire. S’il n’y a pas d’erreur, la méthode enregistre le nouveau film dans la base de données. Dans notre exemple de film, le formulaire n’est pas publié sur le serveur quand des erreurs de validation sont détectées côté client ; la seconde méthode Create n’est jamais appelée quand il y a des erreurs de validation côté client. Si vous désactivez JavaScript dans votre navigateur, la validation client est désactivée et vous pouvez tester la méthode Create HTTP POST ModelState.IsValid pour détecter les erreurs de validation.

Vous pouvez définir un point d’arrêt dans la méthode [HttpPost] Create et vérifier que la méthode n’est jamais appelée. La validation côté client n’enverra pas les données du formulaire quand des erreurs de validation seront détectées. Si vous désactivez JavaScript dans votre navigateur et que vous envoyez ensuite le formulaire avec des erreurs, le point d’arrêt sera atteint. Vous bénéficiez toujours d’une validation complète sans JavaScript.

L’illustration suivante montre comment désactiver JavaScript dans le navigateur Firefox.

Firefox : dans Options, sous l’onglet Contenu, décochez la case Activer Javascript.

L’illustration suivante montre comment désactiver JavaScript dans le navigateur Chrome.

Google Chrome : dans Paramètres de contenu, dans la section Javascript, sélectionnez Interdire à tous les sites d’exécuter JavaScript.

Après la désactivation de JavaScript, publiez les données non valides et parcourez le débogueur.

Pendant le débogage d’une publication de données non valides, Intellisense sur ModelState.IsValid indique que la valeur est false.

Une partie du modèle d’affichage Create.cshtml est indiquée dans le balisage suivant :

<h4>Movie</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>

            @*Markup removed for brevity.*@

Le balisage précédent est utilisé par les méthodes d’action pour afficher le formulaire initial et pour le réafficher en cas d’erreur.

Le Tag Helper Input utilise les attributs DataAnnotations et produit les attributs HTML nécessaires à la validation jQuery côté client. Le Tag Helper Validation affiche les erreurs de validation. Pour plus d’informations, consultez Validation.

Le grand avantage de cette approche est que ni le contrôleur ni le modèle de vue Create ne savent rien des règles de validation appliquées ou des messages d’erreur affichés. Les règles de validation et les chaînes d’erreur sont spécifiées uniquement dans la classe Movie. Ces mêmes règles de validation sont automatiquement appliquées à la vue Edit et à tous les autres modèles de vues que vous pouvez créer et qui modifient votre modèle.

Quand vous devez changer la logique de validation, vous pouvez le faire à un seul endroit en ajoutant des attributs de validation au modèle (dans cet exemple, la classe Movie). Vous n’aurez pas à vous soucier des différentes parties de l’application qui pourraient être incohérentes avec la façon dont les règles sont appliquées. Toute la logique de validation sera définie à un seul emplacement et utilisée partout. Le code est ainsi très propre, facile à mettre à jour et évolutif. Et cela signifie que vous respecterez entièrement le principe DRY.

Utilisation d’attributs DataType

Ouvrez le fichier Movie.cs et examinez la classe Movie. L’espace de noms System.ComponentModel.DataAnnotations fournit des attributs de mise en forme en plus de l’ensemble intégré d’attributs de validation. Nous avons déjà appliqué une valeur d’énumération DataType aux champs de date de sortie et de prix. Le code suivant illustre les propriétés ReleaseDate et Price avec l’attribut DataType approprié.

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

Les attributs DataType fournissent uniquement des indices permettant au moteur de vue de mettre en forme les données (et fournissent des éléments/attributs tels que <a> pour les URL et <a href="mailto:EmailAddress.com"> pour l’e-mail). Vous pouvez utiliser l’attribut RegularExpression pour valider le format des données. L’attribut DataType sert à spécifier un type de données qui est plus spécifique que le type intrinsèque de la base de données ; il ne s’agit pas d’un attribut de validation. Dans le cas présent, nous voulons uniquement effectuer le suivi de la date, et non de l’heure. L’énumération DataType fournit de nombreux types de données, telles que Date, Time, PhoneNumber, Currency ou EmailAddress. L’attribut DataType peut également permettre à l’application de fournir automatiquement des fonctionnalités propres au type. Par exemple, vous pouvez créer un lien mailto: pour DataType.EmailAddress, et vous pouvez fournir un sélecteur de date pour DataType.Date dans les navigateurs qui prennent en charge HTML5. Les attributs DataType émettent des attributs HTML 5 data- compréhensibles par les navigateurs HTML 5. Les attributs DataType ne fournissent aucune validation.

DataType.Date ne spécifie pas le format de la date qui s’affiche. Par défaut, le champ de données est affiché conformément aux formats par défaut basés sur le CultureInfo du serveur.

L’attribut DisplayFormat est utilisé pour spécifier explicitement le format de date :

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

Le paramètre ApplyFormatInEditMode indique que la mise en forme doit également être appliquée quand la valeur est affichée dans une zone de texte à des fins de modification. (Ceci peut ne pas être souhaitable pour certains champs ; par exemple, pour les valeurs monétaires, vous ne souhaiterez sans doute pas que le symbole monétaire figure dans la zone de texte.)

Vous pouvez utiliser l’attribut DisplayFormat par lui-même, mais il est généralement préférable d’utiliser l’attribut DataType. L’attribut DataType donne la sémantique des données, plutôt que de décrire comment effectuer le rendu sur un écran, et il offre les avantages suivants dont vous ne bénéficiez pas avec DisplayFormat :

  • Le navigateur peut activer des fonctionnalités HTML5 (par exemple pour afficher un contrôle de calendrier, le symbole monétaire correspondant aux paramètres régionaux, des liens de messagerie, etc.).

  • Par défaut, le navigateur affiche les données à l’aide du format correspondant à vos paramètres régionaux.

  • L’attribut DataType peut permettre à MVC de choisir le modèle de champ correct pour afficher les données (DisplayFormat, utilisé par lui-même, utilise le modèle de chaîne).

Notes

La validation jQuery ne fonctionne pas avec l’attribut Range et DateTime. Par exemple, le code suivant affiche toujours une erreur de validation côté client, même quand la date se trouve dans la plage spécifiée :

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

Vous devez désactiver la validation de date jQuery pour utiliser l’attribut Range avec DateTime. Il n’est généralement pas recommandé de compiler des dates dures dans vos modèles. Par conséquent, l’utilisation de l’attribut Range et de DateTime est déconseillée.

Le code suivant illustre la combinaison d’attributs sur une seule ligne :

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int Id { get; set; }

        [StringLength(60, MinimumLength = 3)]
        public string Title { get; set; }

        [Display(Name = "Release Date"), DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
        public string Genre { get; set; }

        [Range(1, 100), DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
        public string Rating { get; set; }
    }
}

Dans la partie suivante de la série, nous examinons l’application et nous apportons des améliorations aux méthodes Details et Delete générées automatiquement.

Ressources supplémentaires

Dans cette section :

  • Une logique de validation est ajoutée au modèle Movie.
  • Vous vous assurez que les règles de validation sont appliquées chaque fois qu’un utilisateur crée ou modifie un film.

Ne vous répétez pas

L’un des principes de conception de MVC est « Ne vous répétez pas » (désigné par l’acronyme DRY, Don’t Repeat Yourself). ASP.NET Core MVC vous encourage à spécifier les fonctionnalités ou les comportements une seule fois, puis à utiliser la réflexion partout dans une application. Cela réduit la quantité de code à écrire, et rend le code que vous écrivez moins susceptible aux erreurs et plus facile à tester et à gérer.

La prise en charge de la validation fournie par MVC et Entity Framework Core Code First est un bon exemple du principe DRY en action. Vous pouvez spécifier de façon déclarative des règles de validation à un seul emplacement (dans la classe de modèle), et les règles sont appliquées partout dans l’application.

Ajouter des règles de validation au modèle de film

L’espace de noms DataAnnotations fournit un ensemble d’attributs de validation intégrés qui sont appliqués de façon déclarative à une classe ou à une propriété. DataAnnotations contient également des attributs de mise en forme, comme DataType, qui aident à effectuer la mise en forme et ne fournissent aucune validation.

Mettez à jour la classe Movie pour tirer parti des attributs de validation intégrés Required, StringLength, RegularExpression et Range.

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    [Required]
    public string Title { get; set; }

    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Range(1, 100)]
    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
    [Required]
    [StringLength(30)]
    public string Genre { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
    [StringLength(5)]
    [Required]
    public string Rating { get; set; }
}

Les attributs de validation spécifient le comportement que vous souhaitez appliquer sur les propriétés du modèle sur lesquels ils sont appliqués :

  • Les attributs Required et MinimumLength indiquent qu’une propriété doit avoir une valeur, mais rien n’empêche un utilisateur d’entrer un espace pour satisfaire à cette validation.

  • L’attribut RegularExpression sert à limiter les caractères pouvant être entrés. Dans le code précédent, « Genre » :

    • Doit utiliser seulement des lettres.
    • La première lettre doit être une majuscule. Les espaces sont autorisés, tandis que les nombres et les caractères spéciaux ne le sont pas.
  • L’expression RegularExpression « Rating » :

    • Nécessite que le premier caractère soit une lettre majuscule.
    • Autorise les caractères spéciaux et les chiffres aux emplacements qui suivent. « PG-13 » est valide pour une évaluation, mais échoue pour un « Genre ».
  • L’attribut Range limite une valeur à une plage spécifiée.

  • L’attribut StringLength vous permet de définir la longueur maximale d’une propriété de chaîne, et éventuellement sa longueur minimale.

  • Les types valeur (tels que decimal, int, float et DateTime) sont obligatoires par nature et n’ont pas besoin de l’attribut [Required].

L’application automatique des règles de validation par ASP.NET Core permet d’accroître la fiabilité de votre application. Cela garantit également que vous n’oublierez pas de valider un élément et que vous n’autoriserez pas par inadvertance l’insertion de données incorrectes dans la base de données.

Interface utilisateur des erreurs de validation

Exécutez l’application et accédez au contrôleur Movies.

Appuyez sur le lien Create New pour ajouter un nouveau film. Remplissez le formulaire avec des valeurs non valides. Dès que la validation côté client jQuery détecte l’erreur, elle affiche un message d’erreur.

Formulaire d’affichage de film avec plusieurs erreurs de validation côté client jQuery

Notes

Vous ne pourrez peut-être pas entrer de virgules décimales dans les champs décimaux. Pour prendre en charge la validation jQuery pour les paramètres régionaux autres que l’anglais qui utilisent une virgule (« , ») comme décimale et des formats de date autres que l’anglais des États-Unis, vous devez effectuer des étapes pour localiser votre application. Consultez ce commentaire GitHub 4076 pour savoir comment ajouter une virgule décimale.

Notez que le formulaire a affiché automatiquement un message d’erreur de validation approprié dans chaque champ contenant une valeur non valide. Les erreurs sont appliquées à la fois côté client (à l’aide de JavaScript et jQuery) et côté serveur (au cas où un utilisateur aurait désactivé JavaScript).

L’un des principaux avantages est que vous n’avez pas eu à changer une seule ligne de code dans la classe MoviesController ou dans la vue Create.cshtml pour activer cette interface utilisateur de validation. Le contrôleur et les vues créées précédemment dans ce didacticiel ont détecté les règles de validation que vous avez spécifiées à l’aide des attributs de validation sur les propriétés de la classe de modèle Movie. Testez la validation à l’aide de la méthode d’action Edit. La même validation est appliquée.

Les données de formulaire ne sont pas envoyées au serveur tant qu’il y a des erreurs de validation côté client. Vous pouvez vérifier cela en plaçant un point d’arrêt dans la méthode HTTP Post, en utilisant l’outil Fiddler ou à l’aide des Outils de développement F12.

Fonctionnement de la validation

Vous vous demandez peut-être comment l’interface utilisateur de validation a été générée sans aucune mise à jour du code dans le contrôleur ou dans les vues. Le code suivant montre les deux méthodes Create.

// GET: Movies/Create
public IActionResult Create()
{
    return View();
}

// POST: Movies/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(
    [Bind("ID,Title,ReleaseDate,Genre,Price, Rating")] Movie movie)
{
    if (ModelState.IsValid)
    {
        _context.Add(movie);
        await _context.SaveChangesAsync();
        return RedirectToAction("Index");
    }
    return View(movie);
}

La première méthode d’action (HTTP GET) Create affiche le formulaire de création initial. La deuxième version ([HttpPost]) gère la publication de formulaire. La seconde méthode Create (la version [HttpPost]) appelle ModelState.IsValid pour vérifier si le film a des erreurs de validation. L’appel de cette méthode évalue tous les attributs de validation qui ont été appliqués à l’objet. Si l’objet comporte des erreurs de validation, la méthode Create réaffiche le formulaire. S’il n’y a pas d’erreur, la méthode enregistre le nouveau film dans la base de données. Dans notre exemple de film, le formulaire n’est pas publié sur le serveur quand des erreurs de validation sont détectées côté client ; la seconde méthode Create n’est jamais appelée quand il y a des erreurs de validation côté client. Si vous désactivez JavaScript dans votre navigateur, la validation client est désactivée et vous pouvez tester la méthode Create HTTP POST ModelState.IsValid pour détecter les erreurs de validation.

Vous pouvez définir un point d’arrêt dans la méthode [HttpPost] Create et vérifier que la méthode n’est jamais appelée. La validation côté client n’enverra pas les données du formulaire quand des erreurs de validation seront détectées. Si vous désactivez JavaScript dans votre navigateur et que vous envoyez ensuite le formulaire avec des erreurs, le point d’arrêt sera atteint. Vous bénéficiez toujours d’une validation complète sans JavaScript.

L’illustration suivante montre comment désactiver JavaScript dans le navigateur Firefox.

Firefox : dans Options, sous l’onglet Contenu, décochez la case Activer Javascript.

L’illustration suivante montre comment désactiver JavaScript dans le navigateur Chrome.

Google Chrome : dans Paramètres de contenu, dans la section Javascript, sélectionnez Interdire à tous les sites d’exécuter JavaScript.

Après la désactivation de JavaScript, publiez les données non valides et parcourez le débogueur.

Pendant le débogage d’une publication de données non valides, Intellisense sur ModelState.IsValid indique que la valeur est false.

Une partie du modèle d’affichage Create.cshtml est indiquée dans le balisage suivant :


<h4>Movie</h4>
<hr />
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Title" class="control-label"></label>
                <input asp-for="Title" class="form-control" />
                <span asp-validation-for="Title" class="text-danger"></span>
            </div>           
       
        @*Markup removed for brevity.*@

Le balisage précédent est utilisé par les méthodes d’action pour afficher le formulaire initial et pour le réafficher en cas d’erreur.

Le Tag Helper Input utilise les attributs DataAnnotations et produit les attributs HTML nécessaires à la validation jQuery côté client. Le Tag Helper Validation affiche les erreurs de validation. Pour plus d’informations, consultez Validation.

Le grand avantage de cette approche est que ni le contrôleur ni le modèle de vue Create ne savent rien des règles de validation appliquées ou des messages d’erreur affichés. Les règles de validation et les chaînes d’erreur sont spécifiées uniquement dans la classe Movie. Ces mêmes règles de validation sont automatiquement appliquées à la vue Edit et à tous les autres modèles de vues que vous pouvez créer et qui modifient votre modèle.

Quand vous devez changer la logique de validation, vous pouvez le faire à un seul endroit en ajoutant des attributs de validation au modèle (dans cet exemple, la classe Movie). Vous n’aurez pas à vous soucier des différentes parties de l’application qui pourraient être incohérentes avec la façon dont les règles sont appliquées. Toute la logique de validation sera définie à un seul emplacement et utilisée partout. Le code est ainsi très propre, facile à mettre à jour et évolutif. Et cela signifie que vous respecterez entièrement le principe DRY.

Utilisation d’attributs DataType

Ouvrez le fichier Movie.cs et examinez la classe Movie. L’espace de noms System.ComponentModel.DataAnnotations fournit des attributs de mise en forme en plus de l’ensemble intégré d’attributs de validation. Nous avons déjà appliqué une valeur d’énumération DataType aux champs de date de sortie et de prix. Le code suivant illustre les propriétés ReleaseDate et Price avec l’attribut DataType approprié.

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }

Les attributs DataType fournissent uniquement des indices permettant au moteur de vue de mettre en forme les données (et fournissent des éléments/attributs tels que <a> pour les URL et <a href="mailto:EmailAddress.com"> pour l’e-mail). Vous pouvez utiliser l’attribut RegularExpression pour valider le format des données. L’attribut DataType sert à spécifier un type de données qui est plus spécifique que le type intrinsèque de la base de données ; il ne s’agit pas d’un attribut de validation. Dans le cas présent, nous voulons uniquement effectuer le suivi de la date, et non de l’heure. L’énumération DataType fournit de nombreux types de données, telles que Date, Time, PhoneNumber, Currency ou EmailAddress. L’attribut DataType peut également permettre à l’application de fournir automatiquement des fonctionnalités propres au type. Par exemple, vous pouvez créer un lien mailto: pour DataType.EmailAddress, et vous pouvez fournir un sélecteur de date pour DataType.Date dans les navigateurs qui prennent en charge HTML5. Les attributs DataType émettent des attributs HTML 5 data- compréhensibles par les navigateurs HTML 5. Les attributs DataType ne fournissent aucune validation.

DataType.Date ne spécifie pas le format de la date qui s’affiche. Par défaut, le champ de données est affiché conformément aux formats par défaut basés sur le CultureInfo du serveur.

L’attribut DisplayFormat est utilisé pour spécifier explicitement le format de date :

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

Le paramètre ApplyFormatInEditMode indique que la mise en forme doit également être appliquée quand la valeur est affichée dans une zone de texte à des fins de modification. (Ceci peut ne pas être souhaitable pour certains champs ; par exemple, pour les valeurs monétaires, vous ne souhaiterez sans doute pas que le symbole monétaire figure dans la zone de texte.)

Vous pouvez utiliser l’attribut DisplayFormat par lui-même, mais il est généralement préférable d’utiliser l’attribut DataType. L’attribut DataType donne la sémantique des données, plutôt que de décrire comment effectuer le rendu sur un écran, et il offre les avantages suivants dont vous ne bénéficiez pas avec DisplayFormat :

  • Le navigateur peut activer des fonctionnalités HTML5 (par exemple pour afficher un contrôle de calendrier, le symbole monétaire correspondant aux paramètres régionaux, des liens de messagerie, etc.).

  • Par défaut, le navigateur affiche les données à l’aide du format correspondant à vos paramètres régionaux.

  • L’attribut DataType peut permettre à MVC de choisir le modèle de champ correct pour afficher les données (DisplayFormat, utilisé par lui-même, utilise le modèle de chaîne).

Notes

La validation jQuery ne fonctionne pas avec l’attribut Range et DateTime. Par exemple, le code suivant affiche toujours une erreur de validation côté client, même quand la date se trouve dans la plage spécifiée :

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

Vous devez désactiver la validation de date jQuery pour utiliser l’attribut Range avec DateTime. Il n’est généralement pas recommandé de compiler des dates dures dans vos modèles. Par conséquent, l’utilisation de l’attribut Range et de DateTime est déconseillée.

Le code suivant illustre la combinaison d’attributs sur une seule ligne :

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; }

    [Display(Name = "Release Date"), DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
    public string Genre { get; set; }

    [Range(1, 100), DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
    public string Rating { get; set; }
}

Dans la partie suivante de la série, nous examinons l’application et nous apportons des améliorations aux méthodes Details et Delete générées automatiquement.

Ressources supplémentaires