ASP.NET Core: TagHelper statt UrlHelper für sauberen und lesbaren Code

ASP.NET Core: TagHelper statt UrlHelper für sauberen und lesbaren Code

Im alten ASP.NET MVC gab es eine recht umfangreiche Sammlung an UrlHelpern. Sie wurden zur Generierung von Links und Formular-Elementen wie Labeln oder Textboxen in Razor-Ansichten genutzt. Ihr Vorteil bestand darin, dass die entsprechenden HTML-Elemente automatisch auf Basis der genutzten Komponenten (Model, Route usw) generiert wurden. In einem Formular genügte es daher, beispielsweise den Anzeigetext nur im Model zu ändern – durch die UrlHelper wurde dieser automatisch in der Ansicht ebenfalls gesetzt.

Allerdings gibt es auch Nachteile: Sie bringen zusätzliche Komplexität und verschlechtern dies Lesbarkeit sowie das Verständnis. URL-Parameter und Attribute wie Klassen, Ids oder Data-Felder müssen als anonymes Objekt übergeben werden. Spätestens an einem komplexeren Beispiel wird dies klar:

@Html.ActionLink("Film hinzufügen", "Add", "Movie", new { @categoryId = 4  }, new { @class = "text-center", @id = "add-movie" })
<a href="/Movie/Add?categoryId=4" class="text-center" id="add-movie">Film hinzufügen</a>

Insbesondere für Entwickler die nicht damit vertraut sind ist häufig unklar, was genau eine solche Funktion macht. Dies kann beispielsweise ein Problem werden, wenn ein Designer sich um die Optik einer solchen Anwendung kümmern soll.

Neue TagHelper betten sich in HTML ein

Im neuen ASP.NET Core hat auch Microsoft dies erkannt und ersetzt daher die UrlHelper durch TagHelper. Klingt wie fast das gleiche? Keineswegs: Die statischen C# Klassen wurden komplett entfernt. Stattdessen schreibt man normales HTML, und kann darin bestimmte Attribute benutzen. Sie beginnen alle mit dem Präfix asp- wie etwa asp-controller und werden zur Laufzeit entsprechend ersetzt.

Schauen wir uns ein Beispiel an:

Klassischer UrlHelper

@Html.ActionLink("Film hinzufügen", "Add", "Movie")

Neuer ASP.NET Core TagHelper

<a asp-action="Add" asp-controller="Movie">Film hinzufügen</a>

In beiden Fällen erhalten wir als Ausgabe folgendes HTML:

<a href="/Movie/Add">Film hinzufügen</a>

Der TagHelper generiert aus den Attributen Controller und Action das Linkziel, fügt es in ein neues Attribute namens href ein und entfernt die mit asp beginnenden Attribute. Der Razor-Quellcode ist deutlich besser lesbar, da er letztendlich aus bekanntem HTML mit zusätzlichen Attributen besteht. Dass dies grundsätzlich möglich ist, dürfte spätestens seit den HTML5 data-Attributen niemanden mehr überraschen.

Weitere Beispiele für die Anwendung von TagHelpern

Nicht nur bei einfachen Links können die neuen TagHelper genutzt werden. Microsoft hat sie konsequent integriert, sodass sie die alten UrlHelper vollständig ersetzen können. Im folgenden möchte ich diese mit jeweils einem kurzen Beispiel vorstellen.

Formulare

Web-Formulare waren bislang besonders UrlHelper-Lastig. Im schlimmsten Falle bestanden sie bis auf den Submit-Button vollständig daraus. Auch hier lassen sich nun Controller und Action als Attribut angeben:

<form asp-action="Add" asp-controller="Movie" asp-anti-forgery="true"></form>

Das Attribut asp-anti-forgery ersetzt @Html.AntiForgeryToken, und fügt ein unsichtbares Eingabefeld mit einem Validierungstoken ein. XSRF-Attacken werden so verhindert.

Labels und Eingabefelder für Model-Attribute

Innerhalb von Formularen werden häufig Labels und Eingabefelder für die Eigenschaften des jeweiligen Models verwendet. Das asp-for Attribute legt fest, mit welcher Eigenschaft das Element verknüpft ist.

Zur Verdeutlichung ein sehr einfaches Model eines Filmes:

class Movie {
    [Display(Name = "Filmtitel")]
    public int Title { get; set; }
}

Label und Eingabefeld erstellen wir wie folgt:

@model Movie 

<label asp-for="Title"></label>
<input type="text" asp-for="Title" />

Nach dem selben Prinzip kann ein beliebiges Element mit asp-validate-for zur Validierung erstellt werden, beispielsweise ein div:

<div asp-validate-for="Title"></label>

Die bisher verwendeten Lambda-Attribute wie model => model.Title sind dem Rotstift zum Opfer gefallen. Doch dies heißt nicht, dass nun reine Strings ohne Validierung angegeben werden, denn Visual Studio bietet anhand des Models eine Autovervollständigung:

Außerdem findet eine Validierung statt. Werden Felder angegeben die im Model nicht existieren, wird ein regulärer Fehler erzeugt – Wie bei normalem C# Code, der auf nicht existierende Eigenschaften zugreift.

ASP.NET Core überlässt dem Entwickler die freie Wahl, welche Elemente er verwenden möchte. Bei den bisherigen Hilfsklassen konnten nur vordefinierte Elemente (InputFor, HiddenFor usw.) verwendet werden. Beispielsweise kann eine Textarea genutzt werden, wenn ein größeres Eingabefeld notwendig ist. Als positiver Nebeneffekt können alle HTML-Elemente beliebig Verschachtelt werden. Dies war bisher nur über eigene Hilfsklassen möglich.

Auswahllisten (select)

Bei Auswahllisten hat der Entwickler nun die Wahl zwischen statischen Einträgen oder dynamischen – denn Verschachtelungen sind wie eben erwähnt in ASP.NET Core kein Problem mehr. Im folgenden Beispiel erzeugen wir ein Model Category und fügen eine Liste davon zu unserem Film-Model hinzu:

<select asp-for="Categorys">
    <option value="1">Action</option>
    <option value="2">Drama</option>
    <option value="3">Komödie</option>
</select>

Natürlich können die Einträge nach wie vor dynamisch generiert werden, etwa von einer Datenbank geladen. Dabei unterstützt das asp-items Attribute. Im folgenden erzeugen wir die gleiche Auswahlliste mit einer Liste von Kategorien:

@{ 
    var categorys = new List<Category>() {
        new Category(1, "Action"),
        new Category(2, "Drama"),
        new Category(3, "Komödie")
    };
    var selectListItems = new SelectList(categorys, "Id", "Name");
}
<select asp-for="Categorys" asp-items="selectListItems"></select>

Die aus dem alten ASP.NET MVC Framework bekannte Hilfsklasse SelectList ist erhalten geblieben. Auch die Verwendung unterscheidet sich nicht: Im ersten Parameter wird eine generische Liste übergeben. Der zweite definiert die Bezeichnung des Attributes, welches als value Attribute in den HTML-Select Elementen gesetzt werden soll. Zu guter Letzt folgt die sichtbare Bezeichnung des Eintrages.

Leave a Reply