Teil 9: Hinzufügen der Validierung zu einer ASP.NET Core MVC-App

Hinweis

Dies ist nicht die neueste Version dieses Artikels. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Wichtig

Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.

Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Von Rick Anderson

In diesem Abschnitt

  • Dem Modell Movie wird Validierungslogik hinzugefügt.
  • Sie stellen sicher, dass die Validierungsregeln immer dann erzwungen werden, wenn ein Benutzer einen Film erstellt oder bearbeitet.

Einhalten des DRY-Prinzips

Einer der Entwurfsgrundsätze von MVC ist DRY (Don't Repeat Yourself, keine Wiederholungen). ASP.NET Core MVC unterstützt Sie dabe, Funktionalität und Verhalten nur einmal anzugeben und dann auf die gesamte App zu übertragen. Dadurch reduziert sich der Umfang an Code, den Sie schreiben müssen. Und der Code, den Sie schreiben, ist weniger fehleranfällig, leichter zu testen und einfacher zu verwalten.

Die von MVC und Entity Framework Core Code First angebotene Unterstützung der Validierung ist ein gutes Beispiel für den Einsatz des DRY-Prinzips. Sie können deklarativ Validierungsregeln an zentraler Stelle (in der Modellklasse) angegeben, und die Regeln werden überall in der App erzwungen.

Hinzufügen von Validierungsregeln zum Modell „Movie“

Der Namespace „DataAnnotations“ bietet eine Gruppe integrierter Validierungsattribute, die deklarativ auf eine Klasse oder Eigenschaft angewendet werden. „DataAnnotations“ enthält auch Formatierungsattribute wie DataType, die bei der Formatierung helfen und keinerlei Validierung bereitstellen.

Aktualisieren Sie die Movie-Klasse, sodass die integrierten Überprüfungsattribute Required, StringLength, RegularExpression und Range und das Formatierungsattribut DataType verwendet werden können.

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

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 Anforderung zu erfüllen.

  • Das Attribut RegularExpression wird verwendet, um einzuschränken, welche Zeichen eingegeben werden dürfen. Für „Genre“ im Code oben gilt Folgendes:

    • Es dürfen nur Buchstaben enthalten sein.
    • Der erste Buchstabe muss ein Großbuchstabe sein. Leerzeichen sind zulässig, während Zahlen und Sonderzeichen nicht zulässig sind.
  • Für RegularExpression-„Rating“ (Bewertung) gilt Folgendes:

    • Das erste Zeichen muss ein Großbuchstabe sein.
    • Sonderzeichen und Zahlen sind als darauffolgende Zeichen zulässig. „PG-13“ ist als Bewertung („Rating“) gültig, nicht jedoch als „Genre“.
  • 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 (wie decimal, int, float, DateTime) sind grundsätzlich erforderlich und benötigen nicht das Attribut [Required].

Indem Validierungsregeln von ASP.NET Core automatisch erzwungen werden, wird Ihre App stabiler. Darüber hinaus wird sichergestellt, dass Sie die Validierung nicht vergessen und nicht versehentlich falsche Daten in die Datenbank übernehmen.

Benutzeroberflächenoption für Validierungsfehler

Führen Sie die App aus, und navigieren Sie zum Movies-Controller.

Tippen 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.

Ansichtsformular „Movie“ mit mehreren clientseitigen jQuery-Validierungsfehlern

Hinweis

Sie können unter Umständen keine Dezimaltrennzeichen in Dezimalfelder eingeben. Zur Unterstützung der jQuery-Validierung für nicht englische Gebietsschemas, in denen ein Komma („,“) als Dezimaltrennzeichen verwendet wird, und Nicht-US-englische Datums- und Uhrzeitformate müssen Sie Schritte zur Globalisierung Ihrer App ausführen. In diesem GitHub-Kommentar 4076 finden Sie Anweisungen zum Hinzufügen von Kommas als Dezimaltrennzeichen.

Wie Sie sehen, hat das Formular automatisch für alle Felder mit einem ungültigen Wert eine entsprechende Validierungsfehlermeldung angezeigt. Die Fehlermeldungen werden sowohl auf Clientseite (mithilfe von JavaScript und jQuery) als auch auf Serverseite erzwungen (wenn ein Benutzer JavaScript deaktiviert hat).

Ein entscheidender Vorteil ist, dass Sie nicht eine Codezeile in der MoviesController-Klasse oder in der Ansicht Create.cshtml ändern müssen, um diese Benutzeroberfläche für die Validierung 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 Methode HTTP Post einfügen. Verwenden Sie dazu das Fiddler-Tool oder die F12-Entwicklertools.

Funktionsweise der Validierung

Sie fragen sich vielleicht, wie die Benutzeroberfläche für die Validierung ohne Aktualisierungen von Code im Controller oder in Ansichten generiert wurde. Der folgende Code zeigt die beiden Create-Methoden.

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

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 Movie-Beispiel wird das Formular nicht an den Server gesendet, wenn Validierungsfehler auf der Clientseite erkannt werden. Die zweite Create-Methode wird nicht aufgerufen, wenn clientseitige Validierungsfehler vorhanden sind. Wenn Sie JavaScript in Ihrem Browser deaktivieren, wird die Clientvalidierung deaktiviert, und Sie können die HTTP-POST-Create-Methode testen und mit ModelState.IsValid Validierungsfehler finden.

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 im Firefox-Browser deaktiviert wird.

Firefox: Deaktivieren Sie auf der Registerkarte „Inhalt“ unter „Optionen“ das Kontrollkästchen „Javascript aktivieren“.

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

Google Chrome: Wählen Sie im JavaScript-Abschnitt der Inhaltseinstellungen die Option „Ausführung von JavaScript für keine Webseite zulassen“ aus.

Nachdem Sie JavaScript deaktiviert haben, senden Sie ungültige Daten, und gehen Sie den Debugger durch.

Während des Debuggens von ungültigen Daten zeigt IntelliSense für „ModelState.IsValid“ an, dass der Wert falsch ist.

Ein Teil der Create.cshtml-Ansichtsvorlage wird im folgenden Markup gezeigt:

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

Das obige Markup wird von den Aktionsmethoden verwendet, um das Anfangsformulars anzuzeigen und es im Fall eines Fehlers erneut anzuzeigen.

Das Hilfsprogramm für Eingabetags verwendet die Attribute von DataAnnotations und generiert HTML-Attribute, die auf der Clientseite für die jQuery-Validierung erforderlich sind. Das Hilfsprogramm für Validierungstags zeigt Validierungsfehler. Weitere Informationen finden Sie unter Validierung.

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 Validierungslogik ändern müssen, können Sie dies auch an genau einer Stelle tun, indem Sie Validierungsattribute zum Modell hinzufügen (in diesem Beispiel zur Klasse Movie). 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.

Verwenden von „DataType“-Attributen

Öffnen Sie die Datei Movie.cs, und überprüfen Sie die Movie-Klasse. 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.

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

Die DataType-Attribute geben der Anzeige-Engine nur Hinweise zum Formatieren der Daten und liefern Elemente bzw. Attribute wie <a> für URLs und <a href="mailto:EmailAddress.com"> für E-Mails. Sie können das RegularExpression-Attribut verwenden, um das Format der Daten zu validieren. Das DataType-Attribut wird verwendet, um einen Datentyp anzugeben, der spezifischer als der datenbankinterne Typ ist. Dabei handelt es sich nicht um Validierungsattribute. In diesem Fall möchten wir nur das Datum verfolgen, nicht die Zeit. Die DataType-Enumeration stellt viele Datentypen bereit, wie z.B. „Date“, „Time“, „PhoneNumber“, „Currency“, „EmailAddress“ usw. 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 in Browsern mit Unterstützung für HTML5 für DataType.Date bereitgestellt werden. Die DataType-Attribute geben data--Attribute (ausgesprochen „Datadash“) von HTML5 aus, die HTML5-Browser nutzen können. Die DataType-Attribute bieten keine Validierung.

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

Das DisplayFormat-Attribut dient zum expliziten Angeben des Datumsformats:

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

Die Einstellung ApplyFormatInEditMode gibt an, dass die Formatierung auch angewendet werden soll, wenn der Wert in einem Textfeld zur Bearbeitung angezeigt wird. (Es kann sein, dass Sie dies für einige Felder nicht benötigen. Z.B. ist es sinnvoller, dass für Währungsangaben das Währungssymbol im Textfeld für die Bearbeitung nicht enthalten ist.)

Sie können das DisplayFormat-Attribut eigenständig verwenden, doch meist empfiehlt es sich, das DataType-Attribut zu verwenden. Das DataType-Attribut übermittelt die Semantik der Daten im Gegensatz zu deren Rendern auf einem Bildschirm. Es bietet die folgenden Vorteile, die „DisplayFormat“ nicht bietet:

  • Der Browser kann HTML5-Features aktivieren (z.B. zum Anzeigen eines Kalendersteuerelements, des dem Gebietsschema entsprechenden Währungssymbols, von E-Mail-Links usw.).

  • Standardmäßig rendert der Browser Daten mit dem ordnungsgemäßen auf Ihrem Gebietsschema basierenden Format.

  • Mit dem DataType-Attribut kann MVC die richtige Feldvorlage zum Rendern der Daten auswählen (DisplayFormat, falls eigenständig genutzt, verwendet die Zeichenfolgenvorlage).

Hinweis

Die jQuery-Validierung funktioniert mit den Attributen Range und DateTime nicht. 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-Datumsvalidierung deaktivieren, um das Range-Attribut mit DateTime zu verwenden. Es wird allgemein nicht empfohlen, feste Datumsangaben in Ihren Modellen zu kompilieren, weshalb vom Einsatz des Range-Attributs und von DateTime abgeraten wird.

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

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

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

Zusätzliche Ressourcen

In diesem Abschnitt

  • Dem Modell Movie wird Validierungslogik hinzugefügt.
  • Sie stellen sicher, dass die Validierungsregeln immer dann erzwungen werden, wenn ein Benutzer einen Film erstellt oder bearbeitet.

Einhalten des DRY-Prinzips

Einer der Entwurfsgrundsätze von MVC ist DRY (Don't Repeat Yourself, keine Wiederholungen). ASP.NET Core MVC unterstützt Sie dabe, Funktionalität und Verhalten nur einmal anzugeben und dann auf die gesamte App zu übertragen. Dadurch reduziert sich der Umfang an Code, den Sie schreiben müssen. Und der Code, den Sie schreiben, ist weniger fehleranfällig, leichter zu testen und einfacher zu verwalten.

Die von MVC und Entity Framework Core Code First angebotene Unterstützung der Validierung ist ein gutes Beispiel für den Einsatz des DRY-Prinzips. Sie können deklarativ Validierungsregeln an zentraler Stelle (in der Modellklasse) angegeben, und die Regeln werden überall in der App erzwungen.

Hinzufügen von Validierungsregeln zum Modell „Movie“

Der Namespace „DataAnnotations“ bietet eine Gruppe integrierter Validierungsattribute, die deklarativ auf eine Klasse oder Eigenschaft angewendet werden. „DataAnnotations“ enthält auch Formatierungsattribute wie DataType, die bei der Formatierung helfen und keinerlei Validierung bereitstellen.

Aktualisieren Sie die Movie-Klasse, sodass die integrierten Überprüfungsattribute Required, StringLength, RegularExpression und Range und das Formatierungsattribut DataType verwendet werden können.

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

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 Anforderung zu erfüllen.

  • Das Attribut RegularExpression wird verwendet, um einzuschränken, welche Zeichen eingegeben werden dürfen. Für „Genre“ im Code oben gilt Folgendes:

    • Es dürfen nur Buchstaben enthalten sein.
    • Der erste Buchstabe muss ein Großbuchstabe sein. Leerzeichen sind zulässig, während Zahlen und Sonderzeichen nicht zulässig sind.
  • Für RegularExpression-„Rating“ (Bewertung) gilt Folgendes:

    • Das erste Zeichen muss ein Großbuchstabe sein.
    • Sonderzeichen und Zahlen sind als darauffolgende Zeichen zulässig. „PG-13“ ist als Bewertung („Rating“) gültig, nicht jedoch als „Genre“.
  • 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 (wie decimal, int, float, DateTime) sind grundsätzlich erforderlich und benötigen nicht das Attribut [Required].

Indem Validierungsregeln von ASP.NET Core automatisch erzwungen werden, wird Ihre App stabiler. Darüber hinaus wird sichergestellt, dass Sie die Validierung nicht vergessen und nicht versehentlich falsche Daten in die Datenbank übernehmen.

Benutzeroberflächenoption für Validierungsfehler

Führen Sie die App aus, und navigieren Sie zum Movies-Controller.

Tippen 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.

Ansichtsformular „Movie“ mit mehreren clientseitigen jQuery-Validierungsfehlern

Hinweis

Sie können unter Umständen keine Dezimaltrennzeichen in Dezimalfelder eingeben. Zur Unterstützung der jQuery-Validierung für nicht englische Gebietsschemas, in denen ein Komma („,“) als Dezimaltrennzeichen verwendet wird, und Nicht-US-englische Datums- und Uhrzeitformate müssen Sie Schritte zur Globalisierung Ihrer App ausführen. In diesem GitHub-Kommentar 4076 finden Sie Anweisungen zum Hinzufügen von Kommas als Dezimaltrennzeichen.

Wie Sie sehen, hat das Formular automatisch für alle Felder mit einem ungültigen Wert eine entsprechende Validierungsfehlermeldung angezeigt. Die Fehlermeldungen werden sowohl auf Clientseite (mithilfe von JavaScript und jQuery) als auch auf Serverseite erzwungen (wenn ein Benutzer JavaScript deaktiviert hat).

Ein entscheidender Vorteil ist, dass Sie nicht eine Codezeile in der MoviesController-Klasse oder in der Ansicht Create.cshtml ändern müssen, um diese Benutzeroberfläche für die Validierung 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 Methode HTTP Post einfügen. Verwenden Sie dazu das Fiddler-Tool oder die F12-Entwicklertools.

Funktionsweise der Validierung

Sie fragen sich vielleicht, wie die Benutzeroberfläche für die Validierung ohne Aktualisierungen von Code im Controller oder in Ansichten generiert wurde. Der folgende Code zeigt die beiden Create-Methoden.

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

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 Movie-Beispiel wird das Formular nicht an den Server gesendet, wenn Validierungsfehler auf der Clientseite erkannt werden. Die zweite Create-Methode wird nicht aufgerufen, wenn clientseitige Validierungsfehler vorhanden sind. Wenn Sie JavaScript in Ihrem Browser deaktivieren, wird die Clientvalidierung deaktiviert, und Sie können die HTTP-POST-Create-Methode testen und mit ModelState.IsValid Validierungsfehler finden.

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 im Firefox-Browser deaktiviert wird.

Firefox: Deaktivieren Sie auf der Registerkarte „Inhalt“ unter „Optionen“ das Kontrollkästchen „Javascript aktivieren“.

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

Google Chrome: Wählen Sie im JavaScript-Abschnitt der Inhaltseinstellungen die Option „Ausführung von JavaScript für keine Webseite zulassen“ aus.

Nachdem Sie JavaScript deaktiviert haben, senden Sie ungültige Daten, und gehen Sie den Debugger durch.

Während des Debuggens von ungültigen Daten zeigt IntelliSense für „ModelState.IsValid“ an, dass der Wert falsch ist.

Ein Teil der Create.cshtml-Ansichtsvorlage wird im folgenden Markup gezeigt:

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

Das obige Markup wird von den Aktionsmethoden verwendet, um das Anfangsformulars anzuzeigen und es im Fall eines Fehlers erneut anzuzeigen.

Das Hilfsprogramm für Eingabetags verwendet die Attribute von DataAnnotations und generiert HTML-Attribute, die auf der Clientseite für die jQuery-Validierung erforderlich sind. Das Hilfsprogramm für Validierungstags zeigt Validierungsfehler. Weitere Informationen finden Sie unter Validierung.

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 Validierungslogik ändern müssen, können Sie dies auch an genau einer Stelle tun, indem Sie Validierungsattribute zum Modell hinzufügen (in diesem Beispiel zur Klasse Movie). 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.

Verwenden von „DataType“-Attributen

Öffnen Sie die Datei Movie.cs, und überprüfen Sie die Movie-Klasse. 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.

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

Die DataType-Attribute geben der Anzeige-Engine nur Hinweise zum Formatieren der Daten und liefern Elemente bzw. Attribute wie <a> für URLs und <a href="mailto:EmailAddress.com"> für E-Mails. Sie können das RegularExpression-Attribut verwenden, um das Format der Daten zu validieren. Das DataType-Attribut wird verwendet, um einen Datentyp anzugeben, der spezifischer als der datenbankinterne Typ ist. Dabei handelt es sich nicht um Validierungsattribute. In diesem Fall möchten wir nur das Datum verfolgen, nicht die Zeit. Die DataType-Enumeration stellt viele Datentypen bereit, wie z.B. „Date“, „Time“, „PhoneNumber“, „Currency“, „EmailAddress“ usw. 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 in Browsern mit Unterstützung für HTML5 für DataType.Date bereitgestellt werden. Die DataType-Attribute geben data--Attribute (ausgesprochen „Datadash“) von HTML5 aus, die HTML5-Browser nutzen können. Die DataType-Attribute bieten keine Validierung.

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

Das DisplayFormat-Attribut dient zum expliziten Angeben des Datumsformats:

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

Die Einstellung ApplyFormatInEditMode gibt an, dass die Formatierung auch angewendet werden soll, wenn der Wert in einem Textfeld zur Bearbeitung angezeigt wird. (Es kann sein, dass Sie dies für einige Felder nicht benötigen. Z.B. ist es sinnvoller, dass für Währungsangaben das Währungssymbol im Textfeld für die Bearbeitung nicht enthalten ist.)

Sie können das DisplayFormat-Attribut eigenständig verwenden, doch meist empfiehlt es sich, das DataType-Attribut zu verwenden. Das DataType-Attribut übermittelt die Semantik der Daten im Gegensatz zu deren Rendern auf einem Bildschirm. Es bietet die folgenden Vorteile, die „DisplayFormat“ nicht bietet:

  • Der Browser kann HTML5-Features aktivieren (z.B. zum Anzeigen eines Kalendersteuerelements, des dem Gebietsschema entsprechenden Währungssymbols, von E-Mail-Links usw.).

  • Standardmäßig rendert der Browser Daten mit dem ordnungsgemäßen auf Ihrem Gebietsschema basierenden Format.

  • Mit dem DataType-Attribut kann MVC die richtige Feldvorlage zum Rendern der Daten auswählen (DisplayFormat, falls eigenständig genutzt, verwendet die Zeichenfolgenvorlage).

Hinweis

Die jQuery-Validierung funktioniert mit den Attributen Range und DateTime nicht. 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-Datumsvalidierung deaktivieren, um das Range-Attribut mit DateTime zu verwenden. Es wird allgemein nicht empfohlen, feste Datumsangaben in Ihren Modellen zu kompilieren, weshalb vom Einsatz des Range-Attributs und von DateTime abgeraten wird.

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

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

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

Zusätzliche Ressourcen

In diesem Abschnitt

  • Dem Modell Movie wird Validierungslogik hinzugefügt.
  • Sie stellen sicher, dass die Validierungsregeln immer dann erzwungen werden, wenn ein Benutzer einen Film erstellt oder bearbeitet.

Einhalten des DRY-Prinzips

Einer der Entwurfsgrundsätze von MVC ist DRY (Don't Repeat Yourself, keine Wiederholungen). ASP.NET Core MVC unterstützt Sie dabe, Funktionalität und Verhalten nur einmal anzugeben und dann auf die gesamte App zu übertragen. Dadurch reduziert sich der Umfang an Code, den Sie schreiben müssen. Und der Code, den Sie schreiben, ist weniger fehleranfällig, leichter zu testen und einfacher zu verwalten.

Die von MVC und Entity Framework Core Code First angebotene Unterstützung der Validierung ist ein gutes Beispiel für den Einsatz des DRY-Prinzips. Sie können deklarativ Validierungsregeln an zentraler Stelle (in der Modellklasse) angegeben, und die Regeln werden überall in der App erzwungen.

Hinzufügen von Validierungsregeln zum Modell „Movie“

Der Namespace „DataAnnotations“ bietet eine Gruppe integrierter Validierungsattribute, die deklarativ auf eine Klasse oder Eigenschaft angewendet werden. „DataAnnotations“ enthält auch Formatierungsattribute wie DataType, die bei der Formatierung helfen und keinerlei Validierung bereitstellen.

Aktualisieren Sie die Movie-Klasse, um die integrierten Validierungsattribute Required, StringLength, RegularExpression und Range zu nutzen.

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

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 Anforderung zu erfüllen.

  • Das Attribut RegularExpression wird verwendet, um einzuschränken, welche Zeichen eingegeben werden dürfen. Für „Genre“ im Code oben gilt Folgendes:

    • Es dürfen nur Buchstaben enthalten sein.
    • Der erste Buchstabe muss ein Großbuchstabe sein. Leerzeichen sind zulässig, während Zahlen und Sonderzeichen nicht zulässig sind.
  • Für RegularExpression-„Rating“ (Bewertung) gilt Folgendes:

    • Das erste Zeichen muss ein Großbuchstabe sein.
    • Sonderzeichen und Zahlen sind als darauffolgende Zeichen zulässig. „PG-13“ ist als Bewertung („Rating“) gültig, nicht jedoch als „Genre“.
  • 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 (wie decimal, int, float, DateTime) sind grundsätzlich erforderlich und benötigen nicht das Attribut [Required].

Indem Validierungsregeln von ASP.NET Core automatisch erzwungen werden, wird Ihre App stabiler. Darüber hinaus wird sichergestellt, dass Sie die Validierung nicht vergessen und nicht versehentlich falsche Daten in die Datenbank übernehmen.

Benutzeroberflächenoption für Validierungsfehler

Führen Sie die App aus, und navigieren Sie zum Movies-Controller.

Tippen 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.

Ansichtsformular „Movie“ mit mehreren clientseitigen jQuery-Validierungsfehlern

Hinweis

Sie können unter Umständen keine Dezimaltrennzeichen in Dezimalfelder eingeben. Zur Unterstützung der jQuery-Validierung für nicht englische Gebietsschemas, in denen ein Komma („,“) als Dezimaltrennzeichen verwendet wird, und Nicht-US-englische Datums- und Uhrzeitformate müssen Sie Schritte zur Globalisierung Ihrer App ausführen. In diesem GitHub-Kommentar 4076 finden Sie Anweisungen zum Hinzufügen von Kommas als Dezimaltrennzeichen.

Wie Sie sehen, hat das Formular automatisch für alle Felder mit einem ungültigen Wert eine entsprechende Validierungsfehlermeldung angezeigt. Die Fehlermeldungen werden sowohl auf Clientseite (mithilfe von JavaScript und jQuery) als auch auf Serverseite erzwungen (wenn ein Benutzer JavaScript deaktiviert hat).

Ein entscheidender Vorteil ist, dass Sie nicht eine Codezeile in der MoviesController-Klasse oder in der Ansicht Create.cshtml ändern müssen, um diese Benutzeroberfläche für die Validierung 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 Methode HTTP Post einfügen. Verwenden Sie dazu das Fiddler-Tool oder die F12-Entwicklertools.

Funktionsweise der Validierung

Sie fragen sich vielleicht, wie die Benutzeroberfläche für die Validierung ohne Aktualisierungen von Code im Controller oder in Ansichten generiert wurde. Der folgende Code zeigt die beiden Create-Methoden.

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

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 Movie-Beispiel wird das Formular nicht an den Server gesendet, wenn Validierungsfehler auf der Clientseite erkannt werden. Die zweite Create-Methode wird nicht aufgerufen, wenn clientseitige Validierungsfehler vorhanden sind. Wenn Sie JavaScript in Ihrem Browser deaktivieren, wird die Clientvalidierung deaktiviert, und Sie können die HTTP-POST-Create-Methode testen und mit ModelState.IsValid Validierungsfehler finden.

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 im Firefox-Browser deaktiviert wird.

Firefox: Deaktivieren Sie auf der Registerkarte „Inhalt“ unter „Optionen“ das Kontrollkästchen „Javascript aktivieren“.

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

Google Chrome: Wählen Sie im JavaScript-Abschnitt der Inhaltseinstellungen die Option „Ausführung von JavaScript für keine Webseite zulassen“ aus.

Nachdem Sie JavaScript deaktiviert haben, senden Sie ungültige Daten, und gehen Sie den Debugger durch.

Während des Debuggens von ungültigen Daten zeigt IntelliSense für „ModelState.IsValid“ an, dass der Wert falsch ist.

Ein Teil der Create.cshtml-Ansichtsvorlage wird im folgenden Markup gezeigt:

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

Das obige Markup wird von den Aktionsmethoden verwendet, um das Anfangsformulars anzuzeigen und es im Fall eines Fehlers erneut anzuzeigen.

Das Hilfsprogramm für Eingabetags verwendet die Attribute von DataAnnotations und generiert HTML-Attribute, die auf der Clientseite für die jQuery-Validierung erforderlich sind. Das Hilfsprogramm für Validierungstags zeigt Validierungsfehler. Weitere Informationen finden Sie unter Validierung.

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 Validierungslogik ändern müssen, können Sie dies auch an genau einer Stelle tun, indem Sie Validierungsattribute zum Modell hinzufügen (in diesem Beispiel zur Klasse Movie). 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.

Verwenden von „DataType“-Attributen

Öffnen Sie die Datei Movie.cs, und überprüfen Sie die Movie-Klasse. 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.

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

Die DataType-Attribute geben der Anzeige-Engine nur Hinweise zum Formatieren der Daten und liefern Elemente bzw. Attribute wie <a> für URLs und <a href="mailto:EmailAddress.com"> für E-Mails. Sie können das RegularExpression-Attribut verwenden, um das Format der Daten zu validieren. Das DataType-Attribut wird verwendet, um einen Datentyp anzugeben, der spezifischer als der datenbankinterne Typ ist. Dabei handelt es sich nicht um Validierungsattribute. In diesem Fall möchten wir nur das Datum verfolgen, nicht die Zeit. Die DataType-Enumeration stellt viele Datentypen bereit, wie z.B. „Date“, „Time“, „PhoneNumber“, „Currency“, „EmailAddress“ usw. 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 in Browsern mit Unterstützung für HTML5 für DataType.Date bereitgestellt werden. Die DataType-Attribute geben data--Attribute (ausgesprochen „Datadash“) von HTML5 aus, die HTML5-Browser nutzen können. Die DataType-Attribute bieten keine Validierung.

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

Das DisplayFormat-Attribut dient zum expliziten Angeben des Datumsformats:

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

Die Einstellung ApplyFormatInEditMode gibt an, dass die Formatierung auch angewendet werden soll, wenn der Wert in einem Textfeld zur Bearbeitung angezeigt wird. (Es kann sein, dass Sie dies für einige Felder nicht benötigen. Z.B. ist es sinnvoller, dass für Währungsangaben das Währungssymbol im Textfeld für die Bearbeitung nicht enthalten ist.)

Sie können das DisplayFormat-Attribut eigenständig verwenden, doch meist empfiehlt es sich, das DataType-Attribut zu verwenden. Das DataType-Attribut übermittelt die Semantik der Daten im Gegensatz zu deren Rendern auf einem Bildschirm. Es bietet die folgenden Vorteile, die „DisplayFormat“ nicht bietet:

  • Der Browser kann HTML5-Features aktivieren (z.B. zum Anzeigen eines Kalendersteuerelements, des dem Gebietsschema entsprechenden Währungssymbols, von E-Mail-Links usw.).

  • Standardmäßig rendert der Browser Daten mit dem ordnungsgemäßen auf Ihrem Gebietsschema basierenden Format.

  • Mit dem DataType-Attribut kann MVC die richtige Feldvorlage zum Rendern der Daten auswählen (DisplayFormat, falls eigenständig genutzt, verwendet die Zeichenfolgenvorlage).

Hinweis

Die jQuery-Validierung funktioniert mit den Attributen Range und DateTime nicht. 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-Datumsvalidierung deaktivieren, um das Range-Attribut mit DateTime zu verwenden. Es wird allgemein nicht empfohlen, feste Datumsangaben in Ihren Modellen zu kompilieren, weshalb vom Einsatz des Range-Attributs und von DateTime abgeraten wird.

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

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

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

Zusätzliche Ressourcen

In diesem Abschnitt

  • Dem Modell Movie wird Validierungslogik hinzugefügt.
  • Sie stellen sicher, dass die Validierungsregeln immer dann erzwungen werden, wenn ein Benutzer einen Film erstellt oder bearbeitet.

Einhalten des DRY-Prinzips

Einer der Entwurfsgrundsätze von MVC ist DRY (Don't Repeat Yourself, keine Wiederholungen). ASP.NET Core MVC unterstützt Sie dabe, Funktionalität und Verhalten nur einmal anzugeben und dann auf die gesamte App zu übertragen. Dadurch reduziert sich der Umfang an Code, den Sie schreiben müssen. Und der Code, den Sie schreiben, ist weniger fehleranfällig, leichter zu testen und einfacher zu verwalten.

Die von MVC und Entity Framework Core Code First angebotene Unterstützung der Validierung ist ein gutes Beispiel für den Einsatz des DRY-Prinzips. Sie können deklarativ Validierungsregeln an zentraler Stelle (in der Modellklasse) angegeben, und die Regeln werden überall in der App erzwungen.

Hinzufügen von Validierungsregeln zum Modell „Movie“

Der Namespace „DataAnnotations“ bietet eine Gruppe integrierter Validierungsattribute, die deklarativ auf eine Klasse oder Eigenschaft angewendet werden. „DataAnnotations“ enthält auch Formatierungsattribute wie DataType, die bei der Formatierung helfen und keinerlei Validierung bereitstellen.

Aktualisieren Sie die Movie-Klasse, um die integrierten Validierungsattribute Required, StringLength, RegularExpression und Range zu nutzen.

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

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 Anforderung zu erfüllen.

  • Das Attribut RegularExpression wird verwendet, um einzuschränken, welche Zeichen eingegeben werden dürfen. Für „Genre“ im Code oben gilt Folgendes:

    • Es dürfen nur Buchstaben enthalten sein.
    • Der erste Buchstabe muss ein Großbuchstabe sein. Leerzeichen sind zulässig, während Zahlen und Sonderzeichen nicht zulässig sind.
  • Für RegularExpression-„Rating“ (Bewertung) gilt Folgendes:

    • Das erste Zeichen muss ein Großbuchstabe sein.
    • Sonderzeichen und Zahlen sind als darauffolgende Zeichen zulässig. „PG-13“ ist als Bewertung („Rating“) gültig, nicht jedoch als „Genre“.
  • 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 (wie decimal, int, float, DateTime) sind grundsätzlich erforderlich und benötigen nicht das Attribut [Required].

Indem Validierungsregeln von ASP.NET Core automatisch erzwungen werden, wird Ihre App stabiler. Darüber hinaus wird sichergestellt, dass Sie die Validierung nicht vergessen und nicht versehentlich falsche Daten in die Datenbank übernehmen.

Benutzeroberflächenoption für Validierungsfehler

Führen Sie die App aus, und navigieren Sie zum Movies-Controller.

Tippen 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.

Ansichtsformular „Movie“ mit mehreren clientseitigen jQuery-Validierungsfehlern

Hinweis

Sie können unter Umständen keine Dezimaltrennzeichen in Dezimalfelder eingeben. Zur Unterstützung der jQuery-Validierung für nicht englische Gebietsschemas, in denen ein Komma („,“) als Dezimaltrennzeichen verwendet wird, und Nicht-US-englische Datums- und Uhrzeitformate müssen Sie Schritte zur Globalisierung Ihrer App ausführen. In diesem GitHub-Kommentar 4076 finden Sie Anweisungen zum Hinzufügen von Kommas als Dezimaltrennzeichen.

Wie Sie sehen, hat das Formular automatisch für alle Felder mit einem ungültigen Wert eine entsprechende Validierungsfehlermeldung angezeigt. Die Fehlermeldungen werden sowohl auf Clientseite (mithilfe von JavaScript und jQuery) als auch auf Serverseite erzwungen (wenn ein Benutzer JavaScript deaktiviert hat).

Ein entscheidender Vorteil ist, dass Sie nicht eine Codezeile in der MoviesController-Klasse oder in der Ansicht Create.cshtml ändern müssen, um diese Benutzeroberfläche für die Validierung 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 Methode HTTP Post einfügen. Verwenden Sie dazu das Fiddler-Tool oder die F12-Entwicklertools.

Funktionsweise der Validierung

Sie fragen sich vielleicht, wie die Benutzeroberfläche für die Validierung ohne Aktualisierungen von Code im Controller oder in Ansichten generiert wurde. Der folgende Code zeigt die beiden Create-Methoden.

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

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 Movie-Beispiel wird das Formular nicht an den Server gesendet, wenn Validierungsfehler auf der Clientseite erkannt werden. Die zweite Create-Methode wird nicht aufgerufen, wenn clientseitige Validierungsfehler vorhanden sind. Wenn Sie JavaScript in Ihrem Browser deaktivieren, wird die Clientvalidierung deaktiviert, und Sie können die HTTP-POST-Create-Methode testen und mit ModelState.IsValid Validierungsfehler finden.

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 im Firefox-Browser deaktiviert wird.

Firefox: Deaktivieren Sie auf der Registerkarte „Inhalt“ unter „Optionen“ das Kontrollkästchen „Javascript aktivieren“.

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

Google Chrome: Wählen Sie im JavaScript-Abschnitt der Inhaltseinstellungen die Option „Ausführung von JavaScript für keine Webseite zulassen“ aus.

Nachdem Sie JavaScript deaktiviert haben, senden Sie ungültige Daten, und gehen Sie den Debugger durch.

Während des Debuggens von ungültigen Daten zeigt IntelliSense für „ModelState.IsValid“ an, dass der Wert falsch ist.

Der Teil der Create.cshtml-Ansichtsvorlage wird im folgenden Markup gezeigt:


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

Das obige Markup wird von den Aktionsmethoden verwendet, um das Anfangsformulars anzuzeigen und es im Fall eines Fehlers erneut anzuzeigen.

Das Hilfsprogramm für Eingabetags verwendet die Attribute von DataAnnotations und generiert HTML-Attribute, die auf der Clientseite für die jQuery-Validierung erforderlich sind. Das Hilfsprogramm für Validierungstags zeigt Validierungsfehler. Weitere Informationen finden Sie unter Validierung.

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 Validierungslogik ändern müssen, können Sie dies auch an genau einer Stelle tun, indem Sie Validierungsattribute zum Modell hinzufügen (in diesem Beispiel zur Klasse Movie). 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.

Verwenden von „DataType“-Attributen

Öffnen Sie die Datei Movie.cs, und überprüfen Sie die Movie-Klasse. 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.

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

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

Die DataType-Attribute geben der Anzeige-Engine nur Hinweise zum Formatieren der Daten (und liefern Elemente bzw. Attribute wie <a> für URLs und <a href="mailto:EmailAddress.com"> für E-Mail). Sie können das RegularExpression-Attribut verwenden, um das Format der Daten zu validieren. Das DataType-Attribut wird verwendet, um einen Datentyp anzugeben, der spezifischer als der datenbankinterne Typ ist. Dabei handelt es sich nicht um Validierungsattribute. In diesem Fall möchten wir nur das Datum verfolgen, nicht die Zeit. Die DataType-Enumeration stellt viele Datentypen bereit, wie z.B. „Date“, „Time“, „PhoneNumber“, „Currency“, „EmailAddress“ usw. 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 in Browsern mit Unterstützung für HTML5 für DataType.Date bereitgestellt werden. Die DataType-Attribute geben data--Attribute (ausgesprochen „Datadash“) von HTML5 aus, die HTML5-Browser nutzen können. Die DataType-Attribute bieten keine Validierung.

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

Das DisplayFormat-Attribut dient zum expliziten Angeben des Datumsformats:

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

Die Einstellung ApplyFormatInEditMode gibt an, dass die Formatierung auch angewendet werden soll, wenn der Wert in einem Textfeld zur Bearbeitung angezeigt wird. (Es kann sein, dass Sie dies für einige Felder nicht benötigen. Z.B. ist es sinnvoller, dass für Währungsangaben das Währungssymbol im Textfeld für die Bearbeitung nicht enthalten ist.)

Sie können das DisplayFormat-Attribut eigenständig verwenden, doch meist empfiehlt es sich, das DataType-Attribut zu verwenden. Das DataType-Attribut übermittelt die Semantik der Daten im Gegensatz zu deren Rendern auf einem Bildschirm. Es bietet die folgenden Vorteile, die „DisplayFormat“ nicht bietet:

  • Der Browser kann HTML5-Features aktivieren (z.B. zum Anzeigen eines Kalendersteuerelements, des dem Gebietsschema entsprechenden Währungssymbols, von E-Mail-Links usw.).

  • Standardmäßig rendert der Browser Daten mit dem ordnungsgemäßen auf Ihrem Gebietsschema basierenden Format.

  • Mit dem DataType-Attribut kann MVC die richtige Feldvorlage zum Rendern der Daten auswählen (DisplayFormat, falls eigenständig genutzt, verwendet die Zeichenfolgenvorlage).

Hinweis

Die jQuery-Validierung funktioniert mit den Attributen Range und DateTime nicht. 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-Datumsvalidierung deaktivieren, um das Range-Attribut mit DateTime zu verwenden. Es wird allgemein nicht empfohlen, feste Datumsangaben in Ihren Modellen zu kompilieren, weshalb vom Einsatz des Range-Attributs und von DateTime abgeraten wird.

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

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

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

Zusätzliche Ressourcen