Freigeben über


Hinzufügen von Validierungslogik zum Filmmodell

von Rick Anderson

Hinweis

Hier ist eine aktualisierte Version dieses Lernprogramms verfügbar, die ASP.NET MVC 5 und Visual Studio 2013 verwendet. Es ist sicherer, viel einfacher zu folgen und zeigt weitere Features.

In diesem Abschnitt fügen Sie dem Movie Modell Validierungslogik hinzu, und Sie stellen sicher, dass die Gültigkeitsprüfungsregeln jedes Mal erzwungen werden, wenn ein Benutzer versucht, einen Film mithilfe der Anwendung zu erstellen oder zu bearbeiten.

Trocknen der Dinge

Einer der Kerndesign-Tenets von ASP.NET MVC ist DRY ("Nicht selbst wiederholen"). ASP.NET MVC ermutigt Sie, Funktionen oder Verhaltensweisen nur einmal anzugeben und dann überall in einer Anwendung widerzuspiegeln. Dadurch wird die Menge an Code reduziert, den Sie schreiben müssen, und der Code, den Sie schreiben, weniger fehleranfällig und einfacher zu verwalten.

Die Validierungsunterstützung von ASP.NET MVC- und Entity Framework Code First ist ein großartiges Beispiel für das DRY-Prinzip in Aktion. Sie können Gültigkeitsprüfungsregeln deklarativ an einer Zentralen Stelle (in der Modellklasse) angeben, und die Regeln werden überall in der Anwendung erzwungen.

Sehen wir uns an, wie Sie diese Überprüfungsunterstützung in der Filmanwendung nutzen können.

Hinzufügen von Gültigkeitsprüfungsregeln zum Filmmodell

Zunächst fügen Sie der Movie Klasse eine Validierungslogik hinzu.

Öffnen Sie Datei Movie.cs. Fügen Sie oben in der Datei eine using Anweisung hinzu, die auf den System.ComponentModel.DataAnnotations Namespace verweist:

using System.ComponentModel.DataAnnotations;

Beachten Sie, dass der Namespace nicht enthalten System.Webist. DataAnnotations stellt eine integrierte Gruppe von Überprüfungsattributen bereit, die Sie deklarativ auf eine beliebige Klasse oder Eigenschaft anwenden können.

Aktualisieren Sie nun die Movie Klasse, um die integrierten RequiredAttribute und StringLengthRange Validierungsattribute zu nutzen. Verwenden Sie den folgenden Code als Beispiel für die Anwendung der Attribute.

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; }
}

Führen Sie die Anwendung aus, und Sie erhalten erneut den folgenden Laufzeitfehler:

Das Modell, das den Kontext "MovieDBContext" unterstützt, wurde seit der Erstellung der Datenbank geändert. Erwägen Sie die Verwendung von Code First-Migrationen zum Aktualisieren der Datenbank (https://go.microsoft.com/fwlink/?LinkId=238269).

Wir verwenden Migrationen, um das Schema zu aktualisieren. Erstellen Sie die Lösung, und öffnen Sie dann das Paket-Manager Konsolenfenster, und geben Sie die folgenden Befehle ein:

add-migration AddDataAnnotationsMig
update-database

Nach Abschluss dieses Befehls öffnet Visual Studio die Klassendatei, die die neue DbMigration abgeleitete Klasse mit dem angegebenen Namen (AddDataAnnotationsMig) definiert, und in der Up Methode können Sie den Code sehen, der die Schemaeinschränkungen aktualisiert. Die Title Felder Genre sind nicht mehr nullfähig (d. h. Sie müssen einen Wert eingeben), und das Rating Feld hat eine maximale Länge von 5.

Die Validierungsattribute geben das Verhalten an, das Sie in den Modelleigenschaften erzwingen möchten, auf die sie angewendet werden. Das Required Attribut gibt an, dass eine Eigenschaft einen Wert aufweisen muss. In diesem Beispiel muss ein Film Werte für die Title, ReleaseDate, , Genreund Price Eigenschaften aufweisen, um gültig zu sein. Das Attribut Range schränkt einen Wert auf einen bestimmten Bereich ein. Mit dem Attribut StringLength können Sie die maximale Länge einer Zeichenfolgeneigenschaft und optional die minimale Länge festlegen. Systeminterne Typen (z decimal, int, float, DateTime. B. ) sind standardmäßig erforderlich und benötigen Required das Attribut nicht.

Code First stellt sicher, dass die Gültigkeitsprüfungsregeln, die Sie für eine Modellklasse angeben, erzwungen werden, bevor die Anwendung Änderungen in der Datenbank speichert. Der folgende Code löst beispielsweise eine Ausnahme aus, wenn die SaveChanges Methode aufgerufen wird, da mehrere erforderliche Movie Eigenschaftswerte fehlen und der Preis null ist (der außerhalb des gültigen Bereichs liegt).

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  

Durch die automatische Erzwung von Gültigkeitsprüfungsregeln durch .NET Framework wird Ihre Anwendung robuster. Darüber hinaus wird sichergestellt, dass Sie die Validierung nicht vergessen und nicht versehentlich falsche Daten in die Datenbank übernehmen.

Hier ist eine vollständige Codeauflistung für die aktualisierte Movie.cs Datei:

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; }
    }
}

Überprüfungsfehler-UI in ASP.NET MVC

Führen Sie die Anwendung erneut aus, und navigieren Sie zur URL "/Movies ".

Klicken Sie auf den Link "Neu erstellen", um einen neuen Film hinzuzufügen. Füllen Sie das Formular mit einigen ungültigen Werten aus, und klicken Sie dann auf die Schaltfläche "Erstellen ".

8_validationErrors

Hinweis

um die jQuery-Überprüfung für nicht englische Gebietsschemas zu unterstützen, die ein Komma (",") für einen Dezimalkomma verwenden, müssen Sie globalize.js und Ihre spezifischen Kulturen/globalize.cultures.js Datei(aus https://github.com/jquery/globalize ) und JavaScript verwenden, um sie zu verwendenGlobalize.parseFloat. Der folgende Code zeigt die Änderungen an der Datei Views\Movies\Edit.cshtml für die Arbeit mit der Kultur "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>
}

Beachten Sie, dass das Formular automatisch eine rote Rahmenfarbe verwendet hat, um die Textfelder hervorzuheben, die ungültige Daten enthalten, und eine entsprechende Überprüfungsfehlermeldung neben jedem ausgegeben hat. Die Fehlermeldungen werden sowohl auf Clientseite (mithilfe von JavaScript und jQuery) als auch auf Serverseite erzwungen (wenn ein Benutzer JavaScript deaktiviert hat).

Ein echter Vorteil ist, dass Sie keine einzelne Codezeile in der MoviesController Klasse oder in der Create.cshtml-Ansicht ändern müssen, um diese Überprüfungsbenutzeroberfläche zu aktivieren. Die Controller und Ansichten, die Sie zuvor in diesem Tutorial erstellt haben, haben die angegebenen Validierungsregeln automatisch übernommen (mithilfe der Validierungsattribute für die Eigenschaften der Modellklasse Movie).

Möglicherweise haben Sie für die Eigenschaften Title bemerkt, und Genredas erforderliche Attribut wird erst erzwungen, wenn Sie das Formular übermitteln (klicken Sie auf die Schaltfläche 'Erstellen '), oder geben Sie Text in das Eingabefeld ein, und entfernen Sie es. Für ein Feld, das anfangs leer ist (z. B. die Felder in der Ansicht "Erstellen") und die nur das erforderliche Attribut und keine anderen Überprüfungsattribute aufweist, können Sie die folgende Schritte ausführen, um die Überprüfung auszulösen:

  1. Drücken Sie die TAB-TASTE in das Feld.
  2. Geben Sie Text ein.
  3. Wechseln Sie durch Drücken der TAB-Taste zum nächsten Feld.
  4. Drücken Sie die TAB-TASTE zurück in das Feld.
  5. Entfernen Sie den Text.
  6. Wechseln Sie durch Drücken der TAB-Taste zum nächsten Feld.

Die obige Sequenz löst die erforderliche Überprüfung aus, ohne auf die Schaltfläche "Absenden" zu klicken. Wenn Sie einfach auf die Schaltfläche "Senden" klicken, ohne eines der Felder einzugeben, wird die clientseitige Überprüfung ausgelöst. Die Formulardaten werden erst an den Server gesendet, wenn auf Clientseite keine Validierungsfehler mehr auftreten. Sie können dies testen, indem Sie einen Haltepunkt in die HTTP Post-Methode einfügen oder das Fiddler-Tool oder die IE 9 F12-Entwicklertools verwenden.

Screenshot der Seite

Funktionsweise der Überprüfung in der Create View- und Create-Aktionsmethode

Sie fragen sich vielleicht, wie die Benutzeroberfläche für die Validierung ohne Aktualisierungen von Code im Controller oder in Ansichten generiert wurde. Im nächsten Eintrag wird gezeigt, wie die Create Methoden in der MovieController Klasse aussehen. Sie bleiben unverändert davon, wie Sie sie weiter oben in diesem Lernprogramm erstellt haben.

//
// 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);
}

Die erste Create-Aktionsmethode (HTTP GET) zeigt das erste Formular „Create“ an. Die zweite Version ([HttpPost]) verarbeitet die Formularbereitstellung. Die zweite Create-Methode (die HttpPost-Version) ruft ModelState.IsValid auf, um zu überprüfen, ob der Film Validierungsfehler aufweist. Beim Aufrufen dieser Methode werden alle Validierungsattribute ausgewertet, die auf das Objekt angewendet wurden. Wenn das Objekt Validierungsfehler enthält, zeigt die Create-Methode das Formular erneut an. Wenn keine Fehler vorliegen, speichert die Methode den neuen Film in der Datenbank. In unserem Filmbeispiel, das wir verwenden, wird das Formular nicht auf dem Server gepostet, wenn Auf clientseitige Überprüfungsfehler erkannt werden. Die zweite CreateMethode wird nie aufgerufen. Wenn Sie JavaScript in Ihrem Browser deaktivieren, ist die Clientüberprüfung deaktiviert, und die HTTP POST-Methode Create ruft ModelState.IsValid auf, um zu überprüfen, ob der Film Überprüfungsfehler aufweist.

Sie können einen Haltepunkt in der HttpPost Create-Methode festlegen und überprüfen, ob die Methode tatsächlich niemals aufgerufen wird und die clientseitige Validierung die Formulardaten nicht sendet, wenn Validierungsfehler gefunden werden. Wenn Sie JavaScript in Ihrem Browser deaktivieren und dann das Formular mit Fehlern senden, wird der Haltepunkt erreicht. Sie erhalten auch ohne JavaScript weiterhin eine vollständige Validierung. Die folgende Abbildung zeigt, wie JavaScript in Internet Explorer deaktiviert wird.

Screenshot, der das Fenster

Screenshot des Beitrags

Die folgende Abbildung zeigt, wie JavaScript im Firefox-Browser deaktiviert wird.

Screenshot des Fensters

Die folgende Abbildung zeigt, wie Sie JavaScript mit dem Chrome-Browser deaktivieren.

Screenshot der Seite

Unten sehen Sie die Vorlage "Create.cshtml "-Ansicht, die Sie zuvor im Lernprogramm erstellt haben. Sie wird von den oben erläuterten Aktionsmethoden zum Anzeigen des anfänglichen Formulars und zum erneuten Anzeigen des Formulars bei einem Fehler verwendet.

@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>

Beachten Sie, wie der Code ein Html.EditorFor Hilfsprogramm verwendet, um das <input> Element für jede Movie Eigenschaft auszugeben. Neben diesem Hilfsprogramm handelt es sich um einen Aufruf der Html.ValidationMessageFor Hilfsmethode. Diese beiden Hilfsmethoden arbeiten mit dem Modellobjekt, das vom Controller an die Ansicht übergeben wird (in diesem Fall ein Movie Objekt). Sie suchen automatisch nach überprüfungsattributen, die im Modell angegeben sind, und zeigen fehlermeldungen entsprechend an.

Was wirklich schön bei diesem Ansatz ist, dass weder der Controller noch die Create-Ansichtsvorlage etwas über die tatsächlichen Gültigkeitsprüfungsregeln weiß, die erzwungen werden, oder über die spezifischen Fehlermeldungen angezeigt werden. Die Validierungsregeln und Fehlerzeichenfolgen werden nur in der Movie-Klasse angegeben. Dieselben Gültigkeitsprüfungsregeln werden automatisch auf die Bearbeitungsansicht und alle anderen Ansichtenvorlagen angewendet, die Sie möglicherweise erstellen, um das Modell zu bearbeiten.

Wenn Sie die Validierungslogik später ändern möchten, können Sie dies an genau einer Stelle tun, indem Sie dem Modell Validierungsattribute hinzufügen (in diesem Beispiel die movie Klasse). Sie müssen sich keine Gedanken darüber machen, ob die verschiedenen Teile der Anwendung inkonsistent sind und wie Regeln erzwungen werden: Die gesamte Validierungslogik wird zentral definiert und überall verwendet. Dies hält den Code sehr übersichtlich und vereinfacht die Verwaltung und Entwicklung. Und dies bedeutet, dass Sie das DRY-Prinzip vollständig einhalten.

Hinzufügen von Formatierungen zum Filmmodell

Öffnen Sie die Datei Movie.cs, und überprüfen Sie die Klasse Movie. Der Namespace System.ComponentModel.DataAnnotations stellt zusätzlich zu der integrierten Gruppe von Validierungsattributen Formatierungsattribute bereit. Wir haben bereits einen DataType-Enumerationswert auf die Felder mit dem Veröffentlichungsdatum und dem Preis angewendet. Der folgende Code zeigt die Eigenschaften ReleaseDate und Price mit dem entsprechenden DisplayFormat-Attribut.

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

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

Die DataType Attribute sind keine Überprüfungsattribute, sie werden verwendet, um dem Ansichtsmodul mitzuteilen, wie der HTML-Code gerendert wird. Im obigen Beispiel zeigt das DataType.Date Attribut die Filmdaten nur als Datumsangaben ohne Uhrzeit an. Die folgenden DataType Attribute überprüfen beispielsweise nicht das Format der Daten:

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

Die oben aufgeführten Attribute enthalten nur Hinweise für das Ansichtsmodul, um die Daten zu formatieren (und Attribute wie <z. B. eine> URL und <ein href="mailto:EmailAddress.com"> für E-Mail bereitzustellen. Sie können das RegularExpression-Attribut verwenden, um das Format der Daten zu überprüfen.

Ein alternativer Ansatz zur Verwendung der DataType Attribute können Sie explizit einen DataFormatString Wert festlegen. Der folgende Code zeigt die Veröffentlichungsdatumseigenschaft mit einer Datumsformatzeichenfolge (nämlich "d"). Sie sollten dies verwenden, um anzugeben, dass Sie nicht als Teil des Veröffentlichungsdatums zeitieren möchten.

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

Die vollständige Movie Klasse wird unten angezeigt.

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; }
}

Führen Sie die Anwendung aus, und navigieren Sie zum Movies Controller. Das Veröffentlichungsdatum und der Preis sind schön formatiert. Die folgende Abbildung zeigt das Veröffentlichungsdatum und den Preis unter Verwendung von "fr-FR" als Kultur.

8_format_SM

Die folgende Abbildung zeigt die gleichen Daten, die mit der Standardkultur (Englisch US) angezeigt werden.

Screenshot der Seite

Im nächsten Teil der Reihe überprüfen wir die Anwendung und nehmen einige Verbesserungen an den automatisch generierten Methoden Details und Delete vor.