Taghilfsprogramme in Formularen in ASP.NET Core

Von Rick Anderson, N. Taylor Mullen, Dave Paquette und Jerrie Pelser

In diesem Dokument wird das Arbeiten mit Formularen und mit den HTML-Elementen, die häufig in Formularen verwendet werden, veranschaulicht. Das HTML-Element Form stellt den primären Mechanismus bereit, den Web-Apps zum Bereitstellen von Daten an den Server verwenden. In diesem Dokument werden überwiegend Taghilfsprogramme beschrieben sowie deren Einsatzmöglichkeiten zum produktiven Erstellen von robusten HTML-Formularen. Es wird empfohlen, Introduction to Tag Helpers (Einführung in Taghilfsprogramme) vor diesem Dokument zu lesen.

Häufig stellen HTML-Hilfsprogramme eine Alternative zu einem bestimmten Taghilfsprogramm dar. Allerdings ersetzen Taghilfsprogramme HTML-Hilfsprogramme nicht, und es gibt nicht für jedes HTML-Hilfsprogramm ein Taghilfsprogramm. Wenn es ein alternatives HTML-Hilfsprogramm gibt, wird dies erwähnt.

Das Taghilfsprogramm für Formulare

Das Taghilfsprogramm für Formulare:

  • Generiert den HTML-<FORM>-action-Attributwert für eine MVC-Controlleraktion oder eine benannte Route

  • Generiert ein ausgeblendetes Token für die Anforderungsüberprüfung, um (bei Verwendung mit dem [ValidateAntiForgeryToken]-Attribut in der nachfolgenden HTML-Aktionsmethode) websiteübergreifende Anforderungsfälschung zu verhindern.

  • Stellt das asp-route-<Parameter Name>-Attribut bereit, bei dem <Parameter Name> zu den Routenwerten hinzugefügt wird. Die routeValues-Parameter von Html.BeginForm und Html.BeginRouteForm bieten eine ähnliche Funktionalität.

  • Verfügt über die alternativen HTML-Hilfsprogramme Html.BeginForm und Html.BeginRouteForm

Beispiel:

<form asp-controller="Demo" asp-action="Register" method="post">
    <!-- Input and Submit elements -->
</form>

Das zuvor erwähnte Taghilfsprogramm für Formulare generiert folgenden HTML-Code:

<form method="post" action="/Demo/Register">
    <!-- Input and Submit elements -->
    <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Die MVC-Runtime generiert den action-Attributwert aus den Attributen asp-controller und asp-action des Taghilfsprogramms für Formulare. Das Taghilfsprogramm für Formulare generiert ebenfalls ein ausgeblendetes Token für die Anforderungsüberprüfung, um (bei Verwendung mit dem [ValidateAntiForgeryToken]-Attribut in der nachfolgenden HTML-Aktionsmethode) websiteübergreifende Anforderungsfälschung zu verhindern. Es ist schwierig, ein reines HTML-Formular vor websiteübergreifender Anforderungsfälschung zu schützen. Das Taghilfsprogramm für Formulare stellt diesen Dienst für Sie bereit.

Verwenden einer benannte Route

Das asp-route-Attribut für Taghilfsprogramme kann ebenfalls ein Markup für das HTML-Attribut action generieren. Eine App mit einer Route namens register kann folgendes Markup für die Registrierungsseite verwenden:

<form asp-route="register" method="post">
    <!-- Input and Submit elements -->
</form>

Viele der Ansichten im Ordner Views/Account (dieser wird generiert, wenn Sie eine neue Web-App mit einzelnen Benutzerkonten erstellen) enthalten das Attribut asp-route-returnurl:

<form asp-controller="Account" asp-action="Login"
     asp-route-returnurl="@ViewData["ReturnUrl"]"
     method="post" class="form-horizontal" role="form">

Hinweis

Durch die integrierten Vorlagen wird returnUrl nur automatisch aufgefüllt, wenn Sie versuchen, auf eine autorisierte Ressource zuzugreifen, aber nicht authentifiziert oder autorisiert sind. Wenn Sie versuchen, einen nicht autorisierten Zugriff durchzuführen, leitet die Sicherheitsmiddleware Sie zur Anmeldeseite weiter, bei der returnUrl festgelegt ist.

Das Hilfsprogramm für Formularaktionen

Das Hilfsprogramm für Formularaktionen generiert das formaction-Attribut auf dem generierten <button ...>- oder <input type="image" ...>-Tag. Das formaction-Attribut legt fest, wohin ein Formular seine Daten übermittelt. Es stellt eine Bindung mit den <input>-Elementen des Typs image und den <button>-Elementen her. Das Hilfsprogramm für Formularaktionen ermöglicht die Verwendung von mehreren AnchorTagHelper asp--Attributen, die steuern, welcher formaction-Link für das entsprechende Element generiert wird.

Folgende AnchorTagHelper-Attribute werden zum Steuern des Werts von formaction unterstützt:

attribute BESCHREIBUNG
asp-controller Der Name des Controllers.
asp-action Der Name der Aktionsmethode.
asp-area Der Name des Bereichs.
asp-page Der Name der Razor Page-Seite.
asp-page-handler Der Name des Razor Page-Handlers.
asp-route Der Name der Route.
asp-route-{value} Ein einzelner URL-Routenwert. Beispiel: asp-route-id="1234".
asp-all-route-data Alle Routenwerte.
asp-fragment Das URL-Fragment.

Beispiel des Übermittelns an den Controller

Das folgende Markup sendet das Formular bei Auswahl der Eingabe oder der Schaltfläche an die Index-Aktion von HomeController:

<form method="post">
    <button asp-controller="Home" asp-action="Index">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" asp-controller="Home" 
                                asp-action="Index">
</form>

Das bisherige Markup generiert folgenden HTML-Code:

<form method="post">
    <button formaction="/Home">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" formaction="/Home">
</form>

Beispiel des Übermittelns an die Seite

Das folgende Markup übermittelt das Formular an die AboutRazor Page-Seite:

<form method="post">
    <button asp-page="About">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" asp-page="About">
</form>

Das bisherige Markup generiert folgenden HTML-Code:

<form method="post">
    <button formaction="/About">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" formaction="/About">
</form>

Beispiel des Übermittelns an die Route

Betrachten Sie den /Home/Test-Endpunkt:

public class HomeController : Controller
{
    [Route("/Home/Test", Name = "Custom")]
    public string Test()
    {
        return "This is the test page";
    }
}

Das folgende Markup sendet das Formular an den /Home/Test-Endpunkt.

<form method="post">
    <button asp-route="Custom">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" asp-route="Custom">
</form>

Das bisherige Markup generiert folgenden HTML-Code:

<form method="post">
    <button formaction="/Home/Test">Click Me</button>
    <input type="image" src="..." alt="Or Click Me" formaction="/Home/Test">
</form>

Das Taghilfsprogramm für die Eingabe

Das Taghilfsprogramm für die Eingabe bindet ein HTML-Element <input> an einen Modellausdruck in Ihrer razor-Ansicht.

Syntax:

<input asp-for="<Expression Name>">

Das Taghilfsprogramm für die Eingabe:

  • Generiert die HTML-Attribute id und name für den Ausdrucksnamen, der im asp-for-Attribut angegeben ist. asp-for="Property1.Property2" entspricht m => m.Property1.Property2. Der Name des Ausdrucks wird für den asp-for-Attributwert verwendet. Weitere Informationen finden Sie im Abschnitt Ausdrucksnamen.

  • Legt den HTML-Attributwert type basierend auf dem Modelltyp und den Attributen für die Datenanmerkung fest, die auf die Modelleigenschaft angewendet werden.

  • Überschreibt den HTML-Attributwert type nicht, wenn ein solcher festgelegt ist

  • Generiert HTML5-Validierungsattribute aus den Attributen für die Datenanmerkung, die auf Modelleigenschaften angewendet werden

  • Verfügt über eine Überschneidung der HTML-Hilfsprogrammfeatures mit Html.TextBoxFor und Html.EditorFor Weitere Informationen finden Sie im Abschnitt Alternative HTML-Hilfsprogramme für Taghilfsprogramme für die Eingabe.

  • Stellt die starke Typisierung bereit Wenn der Name der Eigenschaft geändert wird und Sie das Taghilfsprogramm nicht aktualisieren, wird Ihnen eine Fehlermeldung ähnlich der Folgenden angezeigt:

    An error occurred during the compilation of a resource required to process
    this request. Please review the following specific error details and modify
    your source code appropriately.
    
    Type expected
    'RegisterViewModel' does not contain a definition for 'Email' and no
    extension method 'Email' accepting a first argument of type 'RegisterViewModel'
    could be found (are you missing a using directive or an assembly reference?)
    

Das Input-Taghilfsprogramm legt das HTML-Attribut type basierend auf dem .NET-Typ fest. In der folgenden Tabelle werden einige (jedoch nicht alle) allgemeine .NET-Typen sowie generierte HTML-Typen aufgeführt.

.NET-Typ Eingabetyp
Bool type="checkbox"
String type="text"
DateTime type="datetime-local"
Byte type="number"
Int type="number"
Single, Double type="number"

In der folgenden Tabelle werden einige allgemeine Attribute für die Datenanmerkung aufgeführt, die das Taghilfsprogramm für die Eingabe bestimmten Eingabetypen zuordnet (nicht jedes Validierungsattribut wird aufgeführt):

attribute Eingabetyp
[EmailAddress] type="email"
[Url] type="url"
[HiddenInput] type="hidden"
[Phone] type="tel"
[DataType(DataType.Password)] type="password"
[DataType(DataType.Date)] type="date"
[DataType(DataType.Time)] type="time"

Beispiel:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
    public class RegisterViewModel
    {
        [Required]
        [EmailAddress]
        [Display(Name = "Email Address")]
        public string Email { get; set; }

        [Required]
        [DataType(DataType.Password)]
        public string Password { get; set; }
    }
}
@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterInput" method="post">
    <label>Email: <input asp-for="Email" /></label> <br />
    <label>Password: <input asp-for="Password" /></label><br />
    <button type="submit">Register</button>
</form>

Der oben stehende Code generiert folgenden HTML-Code:

<form method="post" action="/Demo/RegisterInput">
    Email:
    <input type="email" data-val="true"
            data-val-email="The Email Address field is not a valid email address."
            data-val-required="The Email Address field is required."
            id="Email" name="Email" value=""><br>
    Password:
    <input type="password" data-val="true"
            data-val-required="The Password field is required."
            id="Password" name="Password"><br>
    <button type="submit">Register</button>
    <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Die Datenanmerkungen, die auf die Email- und Password-Eigenschaft angewendet werden, generieren Metadaten im Modell. Das Taghilfsprogramm für die Eingabe nutzt die Metadaten des Modells und erzeugt HTML5-data-val-*-Attribute (siehe Modellvalidierung). Diese Attribute beschreiben das Validierungssteuerelement, das den Eingabefeldern angefügt werden soll. Dadurch wird die unaufdringliche Validierung für HTML5 und jQuery bereitgestellt. Die unaufdringlichen (engl. „unobtrusive“) Attribute weisen das Format data-val-rule="Error Message" auf, wobei rule den Namen der Validierungsregel angibt (z. B. data-val-required, data-val-email, data-val-maxlength usw.). Wenn das Attribut eine Fehlermeldung enthält, wird diese als Wert für das Attribut data-val-rule angezeigt. Es gibt ebenfalls Attribute im Format data-val-ruleName-argumentName="argumentValue", die zusätzliche Details zur Regel bereitstellen, z.B. data-val-maxlength-max="1024".

Wenn Sie mehrere input-Steuerelemente an dieselbe Eigenschaft binden, verwenden die generierten Steuerelemente dieselbe id, wodurch das erzeugte Markup ungültig wird. Um Duplikate zu vermeiden, geben Sie das Attribut id explizit für jedes Steuerelement an.

Rendern einer ausgeblendeten Eingabe für Kontrollkästchen

Kontrollkästchen in HTML5 übermitteln keinen Wert, wenn sie nicht aktiviert sind. Damit ein Standardwert für ein nicht aktiviertes Kontrollkästchen gesendet werden kann, generiert das Taghilfsprogramm für die Eingabe eine zusätzliche ausgeblendete Eingabe für Kontrollkästchen.

Betrachten Sie zum Beispiel das folgende Razor-Markup, das das Taghilfsprogramm für die Eingabe für die boolesche Modelleigenschaft IsChecked verwendet:

<form method="post">
    <input asp-for="@Model.IsChecked" />
    <button type="submit">Submit</button>
</form>

Das obige Razor-Markup generiert ein HTML-Markup ähnlich dem folgenden:

<form method="post">
    <input name="IsChecked" type="checkbox" value="true" />
    <button type="submit">Submit</button>

    <input name="IsChecked" type="hidden" value="false" /> 
</form>

Das vorstehende HTML-Markup enthält eine zusätzliche ausgeblendete Eingabe mit dem Namen IsChecked und dem Wert false. Standardmäßig wird diese ausgeblendete Eingabe am Ende des Formulars gerendert. Bei der Übermittlung des Formulars geschieht Folgendes:

  • Wenn das Kontrollkästchen IsChecked aktiviert ist, werden sowohl true als auch false als Werte übermittelt.
  • Ist das Kontrollkästchen IsChecked nicht aktiviert, wird nur der ausgeblendete Eingabewert false übermittelt.

Der ASP.NET Core-Modellbindungsprozess liest bei der Bindung an einen bool-Wert nur den ersten Wert. Dies führt bei aktivierten Kontrollkästchen zum Ergebnis true und bei nicht aktivierten Kontrollkästchen zum Ergebnis false.

Um das Verhalten beim Rendering der ausgeblendeten Eingabe zu konfigurieren, legen Sie die Eigenschaft CheckBoxHiddenInputRenderMode auf MvcViewOptions.HtmlHelperOptions fest. Beispiel:

services.Configure<MvcViewOptions>(options =>
    options.HtmlHelperOptions.CheckBoxHiddenInputRenderMode =
        CheckBoxHiddenInputRenderMode.None);

Der vorangehende Code deaktiviert das Rendering von ausgeblendeten Eingaben für Kontrollkästchen, indem CheckBoxHiddenInputRenderMode auf CheckBoxHiddenInputRenderMode.None festgelegt wird. Alle verfügbaren Modi für das Rendering finden Sie in der Enumeration CheckBoxHiddenInputRenderMode.

Alternative HTML-Hilfsprogramme zum Taghilfsprogramm für die Eingabe

Html.TextBox, Html.TextBoxFor, Html.Editor und Html.EditorFor verfügen über sich überschneidende Features mit dem Taghilfsprogramm für die Eingabe. Das Taghilfsprogramm für die Eingabe legt das type-Attribut automatisch fest, Html.TextBox und Html.TextBoxFor jedoch nicht. Html.Editor und Html.EditorFor verarbeiten Auflistungen, komplexe Objekte und Vorlagen, das Taghilfsprogramm für die Eingabe jedoch nicht. Das Taghilfsprogramm für die Eingabe, Html.EditorFor und Html.TextBoxFor sind stark typisiert (sie verwenden Lambdaausdrücke), Html.TextBox und Html.Editor hingegen nicht (sie verwenden Ausdrucksnamen).

HtmlAttributes

@Html.Editor() und @Html.EditorFor() verwenden einen speziellen ViewDataDictionary-Eintrag namens htmlAttributes, wenn die Standardvorlagen ausgeführt werden. Dieses Verhalten kann optional mithilfe des additionalViewData-Parameters erweitert werden. Der Schlüssel „htmlAttributes“ berücksichtigt die Groß-/Kleinschreibung nicht. Der Schlüssel „htmlAttributes“ wird ähnlich wie das htmlAttributes-Objekt behandelt, das an Hilfsprogramme für die Eingabe wie @Html.TextBox() übergeben wird.

@Html.EditorFor(model => model.YourProperty, 
  new { htmlAttributes = new { @class="myCssClass", style="Width:100px" } })

Ausdrucksnamen

Der asp-for-Attributwert stellt eine ModelExpression-Klasse sowie die rechte Seite eines Lambdaausdrucks dar. Somit wird asp-for="Property1" im generierten Code zu m => m.Property1. Dadurch benötigen Sie das Präfix Model nicht. Sie können das Zeichen „@“ verwenden, um einen Inlineausdruck zu starten und diesen vor m. zu verschieben:

@{
  var joe = "Joe";
}

<input asp-for="@joe">

Folgendes wird generiert:

<input type="text" id="joe" name="joe" value="Joe">

Mit den Auflistungseigenschaften generiert asp-for="CollectionProperty[23].Member" den gleichen Namen wie asp-for="CollectionProperty[i].Member", wenn i den Wert 23 besitzt.

Wenn ASP.NET Core MVC den Wert von ModelExpression berechnet, werden verschiedene Quellen untersucht, unter anderem ModelState. Gehen Sie von <input type="text" asp-for="Name"> aus. Das berechnete value-Attribut entspricht dem ersten der folgenden Werte, der nicht NULL ist:

  • ModelState-Eintrag mit dem Schlüssel „Name“
  • Ergebnis des Ausdrucks Model.Name

Sie können ebenfalls mithilfe des Eigenschaftenpfads des Ansichtsmodells zu untergeordneten Eigenschaften navigieren. Betrachten Sie eine komplexere Modellklasse, die eine untergeordnete Address-Eigenschaft enthält.

public class AddressViewModel
{
    public string AddressLine1 { get; set; }
}
public class RegisterAddressViewModel
{
    public string Email { get; set; }

    [DataType(DataType.Password)]
    public string Password { get; set; }

    public AddressViewModel Address { get; set; }
}

In der Ansicht wird eine Bindung an Address.AddressLine1 erstellt:

@model RegisterAddressViewModel

<form asp-controller="Demo" asp-action="RegisterAddress" method="post">
    <label>Email: <input asp-for="Email" /></label> <br />
    <label>Password: <input asp-for="Password" /></label><br />
    <label>Address: <input asp-for="Address.AddressLine1" /></label><br />
    <button type="submit">Register</button>
</form>

Folgender HTML-Code wird für Address.AddressLine1 generiert:

<input type="text" id="Address_AddressLine1" name="Address.AddressLine1" value="">

Ausdrucksnamen und Auflistungen

Beispiel für ein Modell, das ein Array von Colors enthält:

public class Person
{
    public List<string> Colors { get; set; }

    public int Age { get; set; }
}

Die Aktionsmethode:

public IActionResult Edit(int id, int colorIndex)
{
    ViewData["Index"] = colorIndex;
    return View(GetPerson(id));
}

Die folgende Razor-Syntax veranschaulicht den Zugriff auf ein bestimmtes Color-Element:

@model Person
@{
    var index = (int)ViewData["index"];
}

<form asp-controller="ToDo" asp-action="Edit" method="post">
    @Html.EditorFor(m => m.Colors[index])
    <label asp-for="Age"></label>
    <input asp-for="Age" /><br />
    <button type="submit">Post</button>
</form>

Die Views/Shared/EditorTemplates/String.cshtml-Vorlage:

@model string

<label asp-for="@Model"></label>
<input asp-for="@Model" /> <br />

Beispiel mithilfe von List<T>:

public class ToDoItem
{
    public string Name { get; set; }

    public bool IsDone { get; set; }
}

Die folgende Razor-Syntax veranschaulicht das Durchlaufen einer Auflistung:

@model List<ToDoItem>

<form asp-controller="ToDo" asp-action="Edit" method="post">
    <table>
        <tr> <th>Name</th> <th>Is Done</th> </tr>

        @for (int i = 0; i < Model.Count; i++)
        {
            <tr>
                @Html.EditorFor(model => model[i])
            </tr>
        }

    </table>
    <button type="submit">Save</button>
</form>

Die Views/Shared/EditorTemplates/ToDoItem.cshtml-Vorlage:

@model ToDoItem

<td>
    <label asp-for="@Model.Name"></label>
    @Html.DisplayFor(model => model.Name)
</td>
<td>
    <input asp-for="@Model.IsDone" />
</td>

@*
    This template replaces the following Razor which evaluates the indexer three times.
    <td>
         <label asp-for="@Model[i].Name"></label>
         @Html.DisplayFor(model => model[i].Name)
     </td>
     <td>
         <input asp-for="@Model[i].IsDone" />
     </td>
*@

Wenn der Wert in einem Kontext wie asp-for oder Html.DisplayFor ausgeführt wird, sollte nach Möglichkeit foreach verwendet werden. Allgemein ist for besser als foreach (sofern das Szenario dies zulässt), weil kein Enumerator zugewiesen werden muss. Die Auswertung eines Indexers in einem LINQ-Ausdruck kann jedoch teuer sein und sollte auf ein Mindestmaß reduziert werden.

 

Hinweis

Der oben stehende kommentierte Beispielcode veranschaulicht das Ersetzen eines Lambdaausdrucks mit dem @-Operator, um auf jedes ToDoItem-Objekt in der Liste zuzugreifen.

Das Taghilfsprogramm für Textbereiche

Das Textarea Tag Helper-Taghilfsprogramm ähnelt dem Taghilfsprogramm für die Eingabe.

  • Generiert die id- und name-Attribute sowie die Attribute für die Datenvalidierung aus dem Modell für ein <textarea>-Element.

  • Stellt die starke Typisierung bereit

  • Alternatives HTML-Hilfsprogramm: Html.TextAreaFor

Beispiel:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
    public class DescriptionViewModel
    {
        [MinLength(5)]
        [MaxLength(1024)]
        public string Description { get; set; }
    }
}
@model DescriptionViewModel

<form asp-controller="Demo" asp-action="RegisterTextArea" method="post">
    <textarea asp-for="Description"></textarea>
    <button type="submit">Test</button>
</form>

Folgender HTML-Code wird generiert:

<form method="post" action="/Demo/RegisterTextArea">
  <textarea data-val="true"
   data-val-maxlength="The field Description must be a string or array type with a maximum length of &#x27;1024&#x27;."
   data-val-maxlength-max="1024"
   data-val-minlength="The field Description must be a string or array type with a minimum length of &#x27;5&#x27;."
   data-val-minlength-min="5"
   id="Description" name="Description">
  </textarea>
  <button type="submit">Test</button>
  <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Das Taghilfsprogramm für Bezeichnungen

  • Generiert die Beschriftung und das for-Attribut in einem <label>-Element für einen Ausdrucksnamen.

  • Alternatives HTML-Hilfsprogramm: Html.LabelFor

Label Tag Helper bietet gegenüber einem reinen HTML-Beschriftungselement folgende Vorteile:

  • Sie erhalten den aussagekräftigen Bezeichnungswert aus dem Display-Attribut. Der gewünschte Anzeigename kann sich mit der Zeit ändern, und die Kombination des Display-Attributs und des Taghilfsprogramms für Bezeichnungen wendet Display überall dort an, wo es verwendet wird.

  • Weniger Markup im Quellcode

  • Starke Typisierung mit der Modelleigenschaft

Beispiel:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
    public class SimpleViewModel
    {
        [Required]
        [EmailAddress]
        [Display(Name = "Email Address")]
        public string Email { get; set; }
    }
}

@model SimpleViewModel

<form asp-controller="Demo" asp-action="RegisterLabel" method="post">
    <label asp-for="Email"></label>
    <input asp-for="Email" /> <br />
</form>

Folgender HTML-Code wird für das <label>-Element generiert:

<label for="Email">Email Address</label>

Das Taghilfsprogramm für Bezeichnungen hat den for-Attributwert „Email“ generiert, bei dem es sich um die ID handelt, die dem <input>-Element zugeordnet wird. Die Taghilfsprogramme generieren konsistente id- und for-Elemente, sodass diese ordnungsgemäß zugeordnet werden können. Die Beschriftung in diesem Beispiel ergibt sich aus dem Display-Attribut. Wenn das Modell kein Display-Attribut enthalten hat, würde die Beschriftung dem Eigenschaftsname des Ausdrucks entsprechen. Um die Standardbeschriftung zu überschreiben, fügen Sie eine Beschriftung in das label-Tag ein.

Die Taghilfsprogramme für die Validierung

Es gibt zwei Taghilfsprogramme für die Validierung. Validation Message Tag Helper (zeigt eine Validierungsmeldung für eine einzelne Eigenschaft im Modell an) und Validation Summary Tag Helper (zeigt eine Zusammenfassung der Validierungsfehler an). Input Tag Helper fügt clientseitige HTML5-Validierungsattribute zu Eingabeelementen hinzu, die auf den Attributen für die Datenanmerkung Ihrer Modellklassen basieren. Die Validierung wird ebenfalls auf dem Server ausgeführt. Das Taghilfsprogramm für die Validierung zeigt diese Fehlermeldungen an, wenn ein Validierungsfehler auftritt.

Das Taghilfsprogramm für Validierungsmeldungen

  • Fügt das HTML5-data-valmsg-for="property"-Attribut zum span-Element hinzu, wodurch die Validierungsfehlermeldung an das Eingabefeld der angegebenen Modelleigenschaft angefügt wird. Wenn ein clientseitiger Validierungsfehler auftritt, zeigt jQuery die Fehlermeldung im <span>-Element an.

  • Die Validierung wird ebenfalls auf dem Server ausgeführt. JavaScript ist auf Clients möglicherweise deaktiviert, und einige Validierungen können nur auf Serverseite ausgeführt werden.

  • Alternatives HTML-Hilfsprogramm: Html.ValidationMessageFor

Validation Message Tag Helper wird mit dem asp-validation-for-Attribut eines span-HTML-Elements verwendet.

<span asp-validation-for="Email"></span>

Das Taghilfsprogramm für Validierungsmeldungen generiert folgenden HTML-Code:

<span class="field-validation-valid"
  data-valmsg-for="Email"
  data-valmsg-replace="true"></span>

Im Allgemeinen verwenden Sie Validation Message Tag Helper nach einem Input-Taghilfsprogramm für dieselbe Eigenschaft. Dadurch werden alle Validierungsfehlermeldungen in der Nähe der Eingabe angezeigt, die den Fehler verursacht hat.

Hinweis

Für die clientseitige Validierung müssen Sie über eine Ansicht mit den richtigen JavaScript- und jQuery-Skriptverweisen verfügen. Weitere Informationen finden Sie unter Modellvalidierung.

Wenn ein serverseitiger Validierungsfehler auftritt (wenn Sie z.B. eine benutzerdefinierte serverseitige Validierung durchführen oder die clientseitige Validierung deaktiviert ist), legt MVC diese Fehlermeldung als Text des <span>-Elements fest.

<span class="field-validation-error" data-valmsg-for="Email"
            data-valmsg-replace="true">
   The Email Address field is required.
</span>

Das Taghilfsprogramm für Validierungszusammenfassungen

  • Zielt <div>-Elemente mit dem asp-validation-summary-Attribut an

  • Alternatives HTML-Hilfsprogramm: @Html.ValidationSummary

Validation Summary Tag Helper wird verwendet, um eine Zusammenfassung der Validierungsmeldungen anzuzeigen. Der asp-validation-summary-Attributwert kann Folgendem entsprechen:

asp-validation-summary Validierungsmeldungen werden angezeigt
All Eigenschaften- und Modellebene
ModelOnly Modell
None None

Beispiel

Im folgenden Beispiel enthält das Datenmodell DataAnnotation-Attribute, wodurch Validierungsfehlermeldungen im <input>-Element generiert werden. Das Taghilfsprogramm für die Validierung zeigt diese Fehlermeldung an, wenn ein Validierungsfehler auftritt:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
    public class RegisterViewModel
    {
        [Required]
        [EmailAddress]
        [Display(Name = "Email Address")]
        public string Email { get; set; }

        [Required]
        [DataType(DataType.Password)]
        public string Password { get; set; }
    }
}
@model RegisterViewModel

<form asp-controller="Demo" asp-action="RegisterValidation" method="post">
    <div asp-validation-summary="ModelOnly"></div>
    <label>Email: <input asp-for="Email" /></label> <br />
    <span asp-validation-for="Email"></span><br />
    <label>Password: <input asp-for="Password" /></label><br />
    <span asp-validation-for="Password"></span><br />
    <button type="submit">Register</button>
</form>

Der generierte HTML-Code (wenn das Modell gültig ist):

<form action="/DemoReg/Register" method="post">
  <label>Email: <input name="Email" id="Email" type="email" value=""
   data-val-required="The Email field is required."
   data-val-email="The Email field is not a valid email address."
   data-val="true"></label><br>
  <span class="field-validation-valid" data-valmsg-replace="true"
   data-valmsg-for="Email"></span><br>
  <label>Password: <input name="Password" id="Password" type="password"
   data-val-required="The Password field is required." data-val="true"></label><br>
  <span class="field-validation-valid" data-valmsg-replace="true"
   data-valmsg-for="Password"></span><br>
  <button type="submit">Register</button>
  <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Das Taghilfsprogramm für die Auswahl

  • Generiert das select-Element und die zugehörigen option-Elemente für die Eigenschaften des Modells.

  • Verfügt über die alternativen HTML-Hilfsprogramme Html.DropDownListFor und Html.ListBoxFor

Das Select Tag Helper asp-for gibt den Namen der Modelleigenschaft für das select-Element an, und asp-items legt die option-Elemente fest. Beispiel:

<select asp-for="Country" asp-items="Model.Countries"></select> 

Beispiel:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
    public class CountryViewModel
    {
        public string Country { get; set; }

        public List<SelectListItem> Countries { get; } = new List<SelectListItem>
        {
            new SelectListItem { Value = "MX", Text = "Mexico" },
            new SelectListItem { Value = "CA", Text = "Canada" },
            new SelectListItem { Value = "US", Text = "USA" },
        };
    }
}

Die Index-Methode initialisiert CountryViewModel, legt das ausgewählte Land fest und übergibt dieses an die Index-Ansicht.

public IActionResult Index()
{
    var model = new CountryViewModel();
    model.Country = "CA";
    return View(model);
}

Die HTTP-POST-Methode Index zeigt die Auswahl an:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Index(CountryViewModel model)
{
    if (ModelState.IsValid)
    {
        var msg = model.Country + " selected";
        return RedirectToAction("IndexSuccess", new { message = msg });
    }

    // If we got this far, something failed; redisplay form.
    return View(model);
}

Die Ansicht Index:

@model CountryViewModel

<form asp-controller="Home" asp-action="Index" method="post">
    <select asp-for="Country" asp-items="Model.Countries"></select> 
    <br /><button type="submit">Register</button>
</form>

Diese generiert folgenden HTML-Code (wenn „CA“ ausgewählt ist):

<form method="post" action="/">
     <select id="Country" name="Country">
       <option value="MX">Mexico</option>
       <option selected="selected" value="CA">Canada</option>
       <option value="US">USA</option>
     </select>
       <br /><button type="submit">Register</button>
     <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
   </form>

Hinweis

Es wird nicht empfohlen, ViewBag oder ViewData mit dem Taghilfsprogramm für die Auswahl zu verwenden. Ein Ansichtsmodell kann MVC-Metadaten stabiler bereitstellen und ist in der Regel weniger problematisch.

Beim asp-for-Attributwert handelt es sich um einen Sonderfall, bei dem kein Model-Präfix erforderlich ist. Für andere Attribute von Taghilfsprogrammen (z.B. asp-items) ist dies jedoch erforderlich.

<select asp-for="Country" asp-items="Model.Countries"></select> 

Enumerationsbindung

Häufig ist es sinnvoll, <select> mit einer enum-Eigenschaft zu verwenden und das SelectListItem-Element aus den enum-Werten zu generieren.

Beispiel:

public class CountryEnumViewModel
{
    public CountryEnum EnumCountry { get; set; }
}
using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
    public enum CountryEnum
    {
        [Display(Name = "United Mexican States")]
        Mexico,
        [Display(Name = "United States of America")]
        USA,
        Canada,
        France,
        Germany,
        Spain
    }
}

Die GetEnumSelectList-Methode generiert ein SelectList-Objekt für eine Enumeration.

@model CountryEnumViewModel

<form asp-controller="Home" asp-action="IndexEnum" method="post">
    <select asp-for="EnumCountry" 
            asp-items="Html.GetEnumSelectList<CountryEnum>()">
    </select> 
    <br /><button type="submit">Register</button>
</form>

Sie können die Enumeratorliste mit dem Display-Attribut markieren, um eine umfangreichere Benutzeroberfläche zu erhalten:

using System.ComponentModel.DataAnnotations;

namespace FormsTagHelper.ViewModels
{
    public enum CountryEnum
    {
        [Display(Name = "United Mexican States")]
        Mexico,
        [Display(Name = "United States of America")]
        USA,
        Canada,
        France,
        Germany,
        Spain
    }
}

Folgender HTML-Code wird generiert:

<form method="post" action="/Home/IndexEnum">
    <select data-val="true" data-val-required="The EnumCountry field is required."
            id="EnumCountry" name="EnumCountry">
        <option value="0">United Mexican States</option>
        <option value="1">United States of America</option>
        <option value="2">Canada</option>
        <option value="3">France</option>
        <option value="4">Germany</option>
        <option selected="selected" value="5">Spain</option>
    </select>
    <br /><button type="submit">Register</button>
    <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

Optionsgruppe

Das HTML-Element <optgroup> wird generiert, wenn das Ansichtsmodell mindestens ein SelectListGroup-Objekt enthält.

CountryViewModelGroup teilt die SelectListItem-Elemente den Gruppen „North America“ (Nordamerika) und „Europe“ (Europa) zu:

public class CountryViewModelGroup
{
    public CountryViewModelGroup()
    {
        var NorthAmericaGroup = new SelectListGroup { Name = "North America" };
        var EuropeGroup = new SelectListGroup { Name = "Europe" };

        Countries = new List<SelectListItem>
        {
            new SelectListItem
            {
                Value = "MEX",
                Text = "Mexico",
                Group = NorthAmericaGroup
            },
            new SelectListItem
            {
                Value = "CAN",
                Text = "Canada",
                Group = NorthAmericaGroup
            },
            new SelectListItem
            {
                Value = "US",
                Text = "USA",
                Group = NorthAmericaGroup
            },
            new SelectListItem
            {
                Value = "FR",
                Text = "France",
                Group = EuropeGroup
            },
            new SelectListItem
            {
                Value = "ES",
                Text = "Spain",
                Group = EuropeGroup
            },
            new SelectListItem
            {
                Value = "DE",
                Text = "Germany",
                Group = EuropeGroup
            }
      };
    }

    public string Country { get; set; }

    public List<SelectListItem> Countries { get; }

Die beiden Gruppen werden im Folgenden dargestellt:

Beispiel für Optionsgruppen

Der generierte HTML-Code:

 <form method="post" action="/Home/IndexGroup">
      <select id="Country" name="Country">
          <optgroup label="North America">
              <option value="MEX">Mexico</option>
              <option value="CAN">Canada</option>
              <option value="US">USA</option>
          </optgroup>
          <optgroup label="Europe">
              <option value="FR">France</option>
              <option value="ES">Spain</option>
              <option value="DE">Germany</option>
          </optgroup>
      </select>
      <br /><button type="submit">Register</button>
      <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
 </form>

Mehrfachauswahl

Das Taghilfsprogramm für die Auswahl generiert automatisch das Attribut multiple = "multiple", wenn die im asp-for-Attribut angegebene Eigenschaft eine IEnumerable-Schnittstelle ist. Betrachten Sie beispielsweise folgendes Modell:

using Microsoft.AspNetCore.Mvc.Rendering;
using System.Collections.Generic;

namespace FormsTagHelper.ViewModels
{
    public class CountryViewModelIEnumerable
    {
        public IEnumerable<string> CountryCodes { get; set; }

        public List<SelectListItem> Countries { get; } = new List<SelectListItem>
        {
            new SelectListItem { Value = "MX", Text = "Mexico" },
            new SelectListItem { Value = "CA", Text = "Canada" },
            new SelectListItem { Value = "US", Text = "USA"    },
            new SelectListItem { Value = "FR", Text = "France" },
            new SelectListItem { Value = "ES", Text = "Spain"  },
            new SelectListItem { Value = "DE", Text = "Germany"}
         };
    }
}

Mit folgender Ansicht

@model CountryViewModelIEnumerable

<form asp-controller="Home" asp-action="IndexMultiSelect" method="post">
    <select asp-for="CountryCodes" asp-items="Model.Countries"></select> 
    <br /><button type="submit">Register</button>
</form>

wird der folgende HTML-Code generiert:

<form method="post" action="/Home/IndexMultiSelect">
    <select id="CountryCodes"
    multiple="multiple"
    name="CountryCodes"><option value="MX">Mexico</option>
<option value="CA">Canada</option>
<option value="US">USA</option>
<option value="FR">France</option>
<option value="ES">Spain</option>
<option value="DE">Germany</option>
</select>
    <br /><button type="submit">Register</button>
  <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
</form>

No selection

Wenn Sie die Option „not specified“ auf mehreren Seiten verwenden, können Sie eine Vorlage erstellen, um Wiederholungen aus dem HTML-Code zu entfernen:

@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">
    @Html.EditorForModel()
    <br /><button type="submit">Register</button>
</form>

Die Views/Shared/EditorTemplates/CountryViewModel.cshtml-Vorlage:

@model CountryViewModel

<select asp-for="Country" asp-items="Model.Countries">
    <option value="">--none--</option>
</select>

Das Hinzufügen des HTML-Elements <option> ist nicht auf den Fall Keine Auswahl beschränkt. Durch die folgende Ansichts- und Aktionsmethode wird beispielsweise HTML-Code generiert, der dem oben stehenden Code ähnelt:

public IActionResult IndexNone()
{
    var model = new CountryViewModel();
    model.Countries.Insert(0, new SelectListItem("<none>", ""));
    return View(model);
}
@model CountryViewModel

<form asp-controller="Home" asp-action="IndexEmpty" method="post">
    <select asp-for="Country">
        <option value="">&lt;none&gt;</option>
        <option value="MX">Mexico</option>
        <option value="CA">Canada</option>
        <option value="US">USA</option>
    </select> 
    <br /><button type="submit">Register</button>
</form>

Das richtige <option>-Element (enthält das selected="selected"-Attribut) wird abhängig vom aktuellen Country-Wert ausgewählt.

public IActionResult IndexOption(int id)
{
    var model = new CountryViewModel();
    model.Country = "CA";
    return View(model);
}
 <form method="post" action="/Home/IndexEmpty">
      <select id="Country" name="Country">
          <option value="">&lt;none&gt;</option>
          <option value="MX">Mexico</option>
          <option value="CA" selected="selected">Canada</option>
          <option value="US">USA</option>
      </select>
      <br /><button type="submit">Register</button>
   <input name="__RequestVerificationToken" type="hidden" value="<removed for brevity>">
 </form>

Zusätzliche Ressourcen