Freigeben über


Hinzufügen der Validierung

von Rick Anderson

Hinweis

Eine aktualisierte Version dieses Lernprogramms ist hier mit der neuesten Version von Visual Studio verfügbar. Das neue Lernprogramm verwendet ASP.NET Core MVC, was viele Verbesserungen in diesem Lernprogramm bietet.

Dieses Tutorial vermittelt Informationen zu ASP.NET Core MVC mit Controllern und Ansichten. Razor Pages ist eine neue Alternative in ASP.NET Core, einem seitenbasierten Programmiermodell, das das Erstellen von Web-UI erleichtert und produktiver macht. Es empfiehlt sich, dass Sie sich das Tutorial der Razor Pages vor der MVC-Version ansehen. Das Tutorial zu Razor Pages:

  • Ist einfacher zu befolgen.
  • Behandelt mehr Features.
  • Ist der bevorzugte Ansatz für die entwicklung neuer Apps.

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. Beachten Sie, dass der System.ComponentModel.DataAnnotations 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. (Sie enthält auch Formatierungsattribute wie Datentyp, der bei der Formatierung hilft und keine Überprüfung bereitstellt.)

Aktualisieren Sie nun die Movie Klasse, um die integrierten RequiredAttribute "StringLengthRegularExpression" und Range "Validation" zu nutzen. Ersetzen Sie die Klasse Movie durch den folgenden Code:

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

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

    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime ReleaseDate { get; set; }
  
    [RegularExpression(@"^[A-Z]+[a-zA-Z]*$")]
    [Required]
    [StringLength(30)]
    public string Genre { get; set; }

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

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

Das StringLength Attribut legt die maximale Länge der Zeichenfolge fest und legt diese Einschränkung für die Datenbank fest, daher ändert sich das Datenbankschema. Klicken Sie im Server-Explorer mit der rechten Maustaste auf die Tabelle "Filme", und klicken Sie auf "Tabellendefinition öffnen":

Screenshot, der das Fenster

In der abbildung oben sehen Sie, dass alle Zeichenfolgenfelder auf NVARCHAR (MAX) festgelegt sind. 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 DataAnnotations
update-database

Nach Abschluss dieses Befehls öffnet Visual Studio die Klassendatei, die die neue DbMigration abgeleitete Klasse mit dem angegebenen Namen (DataAnnotations) definiert, und in der Up Methode können Sie den Code sehen, der die Schemaeinschränkungen aktualisiert:

public override void Up()
{
    AlterColumn("dbo.Movies", "Title", c => c.String(maxLength: 60));
    AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false, maxLength: 30));
    AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
}

Das Genre Feld kann nicht mehr null sein (d. a. Sie müssen einen Wert eingeben). Das Rating Feld hat eine maximale Länge von 5 und Title hat eine maximale Länge von 60. Die Mindestlänge von 3 und Title der Bereich, für den sich der Bereich Price befindet, hat keine Schemaänderungen erstellt.

Untersuchen Sie das Filmschema:

Screenshot der Registerkarte

Die Zeichenfolgenfelder zeigen die neuen Längenbeschränkungen an und Genre werden nicht mehr als NULL-Werte überprüft.

Die Validierungsattribute geben das Verhalten an, das Sie in den Modelleigenschaften erzwingen möchten, auf die sie angewendet werden. Die Attribute Required und MinimumLength geben an, dass eine Eigenschaft einen Wert haben muss. Ein Benutzer kann allerdings ein Leerzeichen eingeben, um diese Validierung zu erfüllen. Das RegularExpression-Attribut wird verwendet, um einzuschränken, welche Zeichen eingegeben werden können. Im oben angegebenen Code sind für Genre und Rating nur Buchstaben (keine Leerzeichen, Zahlen und Sonderzeichen) erlaubt. 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. Werttypen (z decimal, int, float, DateTime. B. ) sind inhärent 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 DbEntityValidationException-Ausnahme aus, wenn die SaveChanges Methode aufgerufen wird, da mehrere erforderliche Movie Eigenschaftswerte fehlen:

MovieDBContext db = new MovieDBContext();
Movie movie = new Movie();
movie.Title = "Gone with the Wind";
db.Movies.Add(movie);
db.SaveChanges();        // <= Will throw server side validation exception

Der obige Code löst die folgende Ausnahme aus:

Fehler bei der Überprüfung für eine oder mehrere Entitäten. Weitere Details finden Sie unter der Eigenschaft "EntityValidationErrors".

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.

Überprüfungsfehler-UI in ASP.NET MVC

Führen Sie die Anwendung 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. Wenn die clientseitige jQuery-Validierung den Fehler erkennt, wird eine Fehlermeldung angezeigt.

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 die NuGet-Globalisierung wie zuvor in diesem Lernprogramm beschrieben einschließen.

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). Testen Sie die Validierung mithilfe der Aktionsmethode Edit, und es folgt die gleiche Validierung.

Die Formulardaten werden erst an den Server gesendet, wenn auf Clientseite keine Validierungsfehler mehr auftreten. Sie können dies überprüfen, indem Sie einen Haltepunkt in die HTTP Post-Methode einfügen, indem Sie das Fiddler-Tool oder die IE F12-Entwicklertools verwenden.

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.

public ActionResult Create()
{
    return View();
}
// POST: /Movies/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")] 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) überprüft ModelState.IsValid , ob der Film Überprüfungsfehler aufweist. Durch Abrufen dieser Eigenschaft werden alle Überprüfungsattribute ausgewertet, die auf das Objekt angewendet wurden. Wenn das Objekt Überprüfungsfehler aufweist, zeigt die Create Methode das Formular erneut an. Wenn keine Fehler vorliegen, speichert die Methode den neuen Film in der Datenbank. In unserem Filmbeispiel wird das Formular nicht auf dem Server gepostet, wenn Auf clientseitige Überprüfungsfehler erkannt werden. Die zweite Create Methode wird nie aufgerufen. Wenn Sie JavaScript in Ihrem Browser deaktivieren, ist die Clientüberprüfung deaktiviert, und die HTTP POST-Methode Create wird ModelState.IsValid überprüft, 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 des geöffneten Fensters

Screenshot, der den Beitrag

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

Screenshot des Fensters

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

Screenshot der Java-Skripteinstellung und der Option zum Zulassen oder Deaktivieren.

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>
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()    
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        @Html.ValidationSummary(true)
        <div class="form-group">
            @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title)
            </div>
        </div>
        @*Fields removed for brevity.*@        




        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

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.

Wirklich nützlich an diesem Ansatz ist, dass weder der Controller noch die Ansichtsvorlage Create an den eigentlichen Validierungsregeln, die erzwungen werden, oder den spezifischen Fehlermeldungen, die angezeigt werden, beteiligt sind. Die Validierungsregeln und Fehlerzeichenfolgen werden nur in der Movie-Klasse angegeben. Diese gleichen Validierungsregeln werden automatisch auf die Ansicht Edit und alle anderen Ansichtsvorlagen angewendet, die Sie erstellen und die das Modell 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 das bedeutet, dass Sie das DRY-Prinzip vollständig berücksichtigen werden.

Verwenden von „DataType“-Attributen

Ö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 DataType-Attribut.

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

Die DataType-Attribute bieten nur Hinweise für das Ansichtsmodul, um die Daten zu formatieren (und Attribute wie <a> z. B. für URL und <a href="mailto:EmailAddress.com"> E-Mail bereitzustellen. Sie können das RegularExpression-Attribut verwenden, um das Format der Daten zu überprüfen. Das DataType-Attribut wird verwendet, um einen spezifischeren Datentyp als den systeminternen Datenbanktyp anzugeben, sie sind keine Überprüfungsattribute. In diesem Fall soll nur das Datum verfolgt werden, nicht das Datum und die Zeit. Die DataType-Aufzählung stellt viele Datentypen bereit, z . B. Datum, Uhrzeit, PhoneNumber, Währung, EmailAddress und mehr. Das DataType-Attribut kann der Anwendung auch ermöglichen, typspezifische Features bereitzustellen. Beispielsweise kann ein mailto: Link für DataType.EmailAddress erstellt werden, und eine Datumsauswahl kann für DataType.Date in Browsern bereitgestellt werden, die HTML5 unterstützen. Die DataType-Attribute geben HTML 5-Daten - (ausgeprägte Datenstrich)-Attribute aus, die HTML 5-Browser verstehen können. Die DataType-Attribute stellen keine Überprüfung bereit.

DataType.Date gibt nicht das Format des Datums an, das angezeigt wird. Standardmäßig wird das Datenfeld entsprechend den Standardformaten basierend auf der CultureInfo des Servers angezeigt.

Das DisplayFormat-Attribut dient zum expliziten Angeben des Datumsformats:

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

Die ApplyFormatInEditMode Einstellung gibt an, dass die angegebene Formatierung auch angewendet werden soll, wenn der Wert in einem Textfeld zum Bearbeiten angezeigt wird. (Möglicherweise möchten Sie dies für einige Felder nicht, z. B. für Währungswerte, das Währungssymbol im Textfeld zur Bearbeitung nicht verwenden.)

Sie können das DisplayFormat-Attribut selbst verwenden, in der Regel ist es jedoch ratsam, auch das DataType-Attribut zu verwenden. Das DataType Attribut vermittelt die Semantik der Daten im Gegensatz zum Rendern auf einem Bildschirm und bietet die folgenden Vorteile, die Sie nicht erhalten DisplayFormat:

  • Der Browser kann HTML5-Features aktivieren (z. B. zum Anzeigen eines Kalendersteuerelements, des gebietsschemabezogenen Währungssymbols, E-Mail-Links usw.).
  • Standardmäßig rendert der Browser Daten mithilfe des richtigen Formats basierend auf Ihrem Gebietsschema.
  • Mit dem DataType-Attribut kann MVC die richtige Feldvorlage auswählen, um die Daten zu rendern (das DisplayFormat , wenn es von sich selbst verwendet wird, verwendet die Zeichenfolgenvorlage). Weitere Informationen finden Sie unter Brad Wilsons ASP.NET MVC 2 Templates. (Obwohl für MVC 2 geschrieben, gilt dieser Artikel weiterhin für die aktuelle Version von ASP.NET MVC.)

Wenn Sie das DataType Attribut mit einem Datumsfeld verwenden, müssen Sie das DisplayFormat Attribut auch angeben, um sicherzustellen, dass das Feld in Chrome-Browsern ordnungsgemäß gerendert wird. Weitere Informationen finden Sie in diesem StackOverflow-Thread.

Hinweis

die jQuery-Überprüfung funktioniert nicht mit dem Range-Attribut und DateTime. Bei folgendem Code wird z.B. stets ein clientseitiger Validierungsfehler angezeigt, auch wenn sich das Datum im angegebenen Bereich befindet:

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

Sie müssen die jQuery-Datumsüberprüfung deaktivieren, um das Range-Attribut mit DateTime zu verwenden. Es empfiehlt sich in der Regel nicht, feste Datumsangaben in Ihren Modellen zu kompilieren, daher wird die Verwendung des Range-Attributs und DateTime abgeraten.

Der folgende Code zeigt die Kombination von Attributen in einer Zeile:

public class Movie
{
   public int ID { get; set; }
   [Required,StringLength(60, MinimumLength = 3)]
   public string Title { get; set; }
   [Display(Name = "Release Date"),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; }
   [Required,StringLength(5)]
   public string Rating { get; set; }
}

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