Partager via


Ajout d’une logique de validation au modèle vidéo

par Rick Anderson

Remarque

Une version mise à jour de ce didacticiel est disponible ici qui utilise ASP.NET MVC 5 et Visual Studio 2013. Il est plus sécurisé, beaucoup plus simple à suivre et montre plus de fonctionnalités.

Dans cette section, vous allez ajouter une logique de validation au Movie modèle et vous vous assurerez que les règles de validation sont appliquées chaque fois qu’un utilisateur tente de créer ou de modifier un film à l’aide de l’application.

Garder les choses sèches

L’un des principaux principes de conception de ASP.NET MVC est DRY (« Ne pas répéter vous-même »). ASP.NET MVC vous encourage à spécifier des fonctionnalités ou un comportement une seule fois, puis à les refléter partout dans une application. Cela réduit la quantité de code dont vous avez besoin pour écrire et rend le code que vous écrivez moins sujette à des erreurs et plus facile à gérer.

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

Examinons comment tirer parti de cette prise en charge de validation dans l’application vidéo.

Ajout de règles de validation au modèle vidéo

Vous commencerez par ajouter une logique de validation à la Movie classe.

Ouvrez le fichier Movie.cs. Ajoutez une using instruction en haut du fichier qui fait référence à l’espace System.ComponentModel.DataAnnotations de noms :

using System.ComponentModel.DataAnnotations;

Notez que l’espace de noms ne contient System.Webpas . DataAnnotations fournit un ensemble intégré d’attributs de validation que vous pouvez appliquer de manière déclarative à n’importe quelle classe ou propriété.

À présent, mettez à jour la Movie classe pour tirer parti des attributs intégrés Required, StringLengthet Range de validation. Utilisez le code suivant comme exemple d’où appliquer les attributs.

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

    [Required]
    public string Title { get; set; }

    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Required]
    public string Genre { get; set; }

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

    [StringLength(5)]
    public string Rating { get; set; }
}

Exécutez l’application et vous obtiendrez à nouveau l’erreur d’exécution suivante :

Le modèle qui sauvegarde le contexte « MovieDBContext » a changé depuis la création de la base de données. Envisagez d’utiliser Migrations Code First pour mettre à jour la base de données (https://go.microsoft.com/fwlink/?LinkId=238269).

Nous allons utiliser des migrations pour mettre à jour le schéma. Générez la solution, puis ouvrez la fenêtre Gestionnaire de package console, puis entrez les commandes suivantes :

add-migration AddDataAnnotationsMig
update-database

Une fois cette commande terminée, Visual Studio ouvre le fichier de classe qui définit la nouvelle DbMigration classe dérivée avec le nom spécifié (AddDataAnnotationsMig), et dans la Up méthode, vous pouvez voir le code qui met à jour les contraintes de schéma. Les Title champs et Genre les champs ne sont plus nullables (autrement dit, vous devez entrer une valeur) et le Rating champ a une longueur maximale de 5.

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. L’attribut Required indique qu’une propriété doit avoir une valeur ; dans cet exemple, un film doit avoir des valeurs pour les propriétés et Price les TitleReleaseDateGenrepropriétés pour être valides. 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 intrinsèques (par exemple decimal, int, float, DateTime) sont requis par défaut et n’ont pas besoin de l’attribut Required .

Code First garantit que les règles de validation que vous spécifiez sur une classe de modèle sont appliquées avant que l’application enregistre les modifications dans la base de données. Par exemple, le code ci-dessous lève une exception lorsque la SaveChanges méthode est appelée, car plusieurs valeurs de propriété requises Movie sont manquantes et le prix est égal à zéro (qui est hors de la plage valide).

MovieDBContext db = new MovieDBContext();

Movie movie = new Movie();
movie.Title = "Gone with the Wind";
movie.Price = 0.0M;

db.Movies.Add(movie);  
db.SaveChanges();        // <= Will throw server side validation exception  

Le fait de disposer de règles de validation appliquées automatiquement par le .NET Framework permet de rendre votre application plus robuste. 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.

Voici une liste de codes complète pour le fichier de Movie.cs mis à jour :

using System;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;

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

        [Required]
        public string Title { get; set; }

        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [Required]
        public string Genre { get; set; }

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

        [StringLength(5)]
        public string Rating { get; set; }
    }

    public class MovieDBContext : DbContext {
        public DbSet<Movie> Movies { get; set; }
    }
}

Interface utilisateur d’erreur de validation dans ASP.NET MVC

Réexécutez l’application et accédez à l’URL /Movies .

Cliquez sur le lien Créer un nouveau film pour ajouter un nouveau film. Remplissez le formulaire avec des valeurs non valides, puis cliquez sur le bouton Créer .

8_validationErrors

Remarque

pour prendre en charge la validation jQuery pour les paramètres régionaux non anglais qui utilisent une virgule (« , ») pour un point décimal, vous devez inclure des globalize.js et vos cultures/fichiers globalize.cultures.js spécifiques (à partir de https://github.com/jquery/globalize ) et JavaScript à utiliserGlobalize.parseFloat. Le code suivant montre les modifications apportées au fichier Views\Movies\Edit.cshtml pour utiliser la culture « fr-FR » :

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
    <script src="~/Scripts/globalize.js"></script>
    <script src="~/Scripts/globalize.culture.fr-FR.js"></script>
    <script>
        $.validator.methods.number = function (value, element) {
            return this.optional(element) ||
                !isNaN(Globalize.parseFloat(value));
        }
        $(document).ready(function () {
            Globalize.culture('fr-FR');
        });
    </script>
    <script>
        jQuery.extend(jQuery.validator.methods, {    
            range: function (value, element, param) {        
                //Use the Globalization plugin to parse the value        
                var val = $.global.parseFloat(value);
                return this.optional(element) || (
                    val >= param[0] && val <= param[1]);
            }
        });

    </script>
}

Notez que le formulaire a automatiquement utilisé une couleur de bordure rouge pour mettre en surbrillance les zones de texte qui contiennent des données non valides et a émis un message d’erreur de validation approprié en regard de chacun d’eux. 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).

Un avantage réel est que vous n’avez pas besoin de modifier une seule ligne de code dans la classe ou dans la MoviesController vue Create.cshtml afin d’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.

Vous avez peut-être remarqué pour les propriétés Title et Genre, l’attribut requis n’est pas appliqué tant que vous n’avez pas envoyé le formulaire (appuyez sur le bouton Créer ), ou entrez du texte dans le champ d’entrée et supprimez-le. Pour un champ qui est initialement vide (par exemple, les champs de la vue Créer) et qui n’a que l’attribut requis et aucun autre attribut de validation, vous pouvez effectuer les opérations suivantes pour déclencher la validation :

  1. Appuyez sur tabulation dans le champ.
  2. Entrez du texte.
  3. Appuyez sur Tab.
  4. Appuyez sur tabulation dans le champ.
  5. Supprimez le texte.
  6. Appuyez sur Tab.

La séquence ci-dessus déclenche la validation requise sans appuyer sur le bouton Envoyer. Il suffit d’appuyer sur le bouton Envoyer sans entrer les champs pour déclencher la validation côté client. 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 le tester en plaçant un point d’arrêt dans la méthode HTTP Post ou en utilisant l’outil fiddler ou les outils de développement IE 9 F12.

Capture d’écran montrant la page Création de films M V C. Une alerte en regard de Title indique que le champ Titre est requis. Une alerte en regard de Genre indique que le champ Genre est requis.

Comment la validation se produit dans la méthode Create View et Create Action

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. La liste suivante montre à quoi ressemblent les Create méthodes de la MovieController classe. Ils ne sont pas modifiés par rapport à la façon dont vous les avez créés précédemment dans ce tutoriel.

//
// GET: /Movies/Create

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

//
// POST: /Movies/Create

[HttpPost]
public ActionResult Create(Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Movies.Add(movie);
        db.SaveChanges();
        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, nous utilisons, le formulaire n’est pas publié sur le serveur lorsqu’il y a des erreurs de validation détectées côté client ; la deuxième Createméthode n’est jamais appelée. Si vous désactivez JavaScript dans votre navigateur, la validation du client est désactivée et les appels ModelState.IsValid de méthode HTTP POST Create permettent de vérifier si le film a des 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’image suivante montre comment désactiver JavaScript dans Internet Explorer.

Capture d’écran montrant la fenêtre Options Internet ouverte à l’onglet Sécurité. Le niveau personnalisé est en rouge. Dans la fenêtre Paramètres de sécurité, le script actif est défini pour désactiver. La barre de défilement est en rouge.

Capture d’écran montrant le billet H t t p. Si le point d’état du modèle est valide est mis en surbrillance.

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

Capture d’écran montrant la fenêtre Options. Le contenu est sélectionné et l’option Activer le script Java est cochée.

L’image suivante montre comment désactiver JavaScript avec le navigateur Chrome.

Capture d’écran montrant la page Options. Sous le capot, il est sélectionné et en rouge. Dans les paramètres de contenu, le script Java est défini sur Autoriser tous les sites à exécuter le script Java.

Vous trouverez ci-dessous le modèle de vue Create.cshtml que vous avez généré précédemment dans le didacticiel. Il est utilisé par les méthodes d’action ci-dessus à la fois pour afficher le formulaire initial et pour le réafficher en cas d’erreur.

@model MvcMovie.Models.Movie

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Movie</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Title)
            @Html.ValidationMessageFor(model => model.Title)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.ReleaseDate)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ReleaseDate)
            @Html.ValidationMessageFor(model => model.ReleaseDate)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Genre)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Genre)
            @Html.ValidationMessageFor(model => model.Genre)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Price)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Price)
            @Html.ValidationMessageFor(model => model.Price)
        </div>
        <div class="editor-label">
    @Html.LabelFor(model => model.Rating)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Rating)
    @Html.ValidationMessageFor(model => model.Rating)
</div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Notez comment le code utilise un Html.EditorFor assistance pour générer l’élément <input> pour chaque Movie propriété. En regard de cet assistance, il s’agit d’un appel à la méthode d’assistance Html.ValidationMessageFor . Ces deux méthodes d’assistance fonctionnent avec l’objet de modèle passé par le contrôleur à la vue (dans ce cas, un Movie objet). Ils recherchent automatiquement les attributs de validation spécifiés sur le modèle et affichent les messages d’erreur appropriés.

Ce qui est vraiment agréable à propos de cette approche, c’est que ni le contrôleur ni le modèle De vue Créer connaît quoi que ce soit sur les règles de validation réelles appliquées ou sur les messages d’erreur spécifiques 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 à l’affichage Édition et à tous les autres modèles de vues que vous pouvez créer pour modifier votre modèle.

Si vous souhaitez modifier la logique de validation ultérieurement, vous pouvez le faire à un seul endroit en ajoutant des attributs de validation au modèle (dans cet exemple, la movie classe). 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.

Ajout de la mise en forme au modèle vidéo

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 DisplayFormat approprié.

[DataType(DataType.Date)] 
public DateTime ReleaseDate { get; set; }

[DataType(DataType.Currency)] 
public decimal Price { get; set; }

Les DataType attributs ne sont pas des attributs de validation, ils sont utilisés pour indiquer au moteur d’affichage comment afficher le code HTML. Dans l’exemple ci-dessus, l’attribut DataType.Date affiche les dates du film sous forme de dates uniquement, sans heure. Par exemple, les attributs suivants DataType ne valident pas le format des données :

[DataType(DataType.EmailAddress)]
[DataType(DataType.PhoneNumber)]
[DataType(DataType.Url)]

Les attributs répertoriés ci-dessus fournissent uniquement des conseils pour que le moteur d’affichage met en forme les données (et fournissent des attributs tels qu’une <> URL et <un href="mailto:EmailAddress.com »> pour l’e-mail. Vous pouvez utiliser l’attribut RegularExpression pour valider le format des données.

Une autre approche de l’utilisation DataType des attributs vous permet de définir explicitement une DataFormatString valeur. Le code suivant montre la propriété date de publication avec une chaîne de format de date (à savoir , « d »). Vous devez l’utiliser pour spécifier que vous ne souhaitez pas être heureux dans le cadre de la date de publication.

[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime ReleaseDate { get; set; }

La classe complète Movie est indiquée ci-dessous.

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

    [Required]
    public string Title { get; set; }

    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Required]
    public string Genre { get; set; }

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

    [StringLength(5)]
    public string Rating { get; set; }
}

Exécutez l’application et accédez au Movies contrôleur. La date de publication et le prix sont bien mis en forme. L’image ci-dessous montre la date de publication et le prix à l’aide de « fr-FR » comme culture.

8_format_SM

L’image ci-dessous montre les mêmes données affichées avec la culture par défaut (États-Unis anglais).

Capture d’écran montrant la page M V Movie Index avec quatre films répertoriés.

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