Tag Helper

Eintrag zuletzt aktualisiert am: 12.09.2019

Tag Helper sind Tags oder Attribute für Tags in Razor Templates, die von ASP.NET Core auf der Serverseite vor der Auslieferung der Website durch andere Tags oder Eigenschaften ersetzt werden. Tag Helper kann ein Webentwickler in Views (bei ASP.NET Core Model-View-Controller – MVC) oder in Pages (bei ASP.NET Core Razor Pages) einsetzen.
Dies ist vergleichbar mit den Direktiven in Angular; allerdings übersetzt Angular die Direktiven clientseitig (also erst im Browser) in Standard-HTML-Tags. Tag Helper nehmen eine ähnliche Rolle ein wie früher die Webserversteuerelemente in ASP.NET Webforms, sind aber in ihrer Implementierung wesentlich einfacher. Eine Entwurfszeitansicht gibt es hier nicht. Tag Helpers können sich auch auf Standard-HTML-Tags beziehen und diese modifizieren.

Vordefinierte Tag Helper

Microsoft liefert bereites eine Reihe eigener Tags, z.B.
  • <partial>
  • <cache> und
  • <environment>

sowie Tag-Attribute (die mit der Vorsilbe "asp-" beginnen), z.B.
  • asp-controller und asp-action for <form>
  • asp-for für <label>, <input> und <select>
  • asp-append-version für <img>
  • asp-validation-for für <span>

in ASP.NET Core in der Microsoft.AspNetCore.Mvc.TagHelpers.dll mit.

Damit diese Tag Helper überhaupt nutzbar sind, müssen Sie mit @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers eingebunden werden. Dies erledigt Microsoft freundlicherweise in den Projektvorlage "Web Application" und "Web Application (MVC)" schon in der Datei /Shared/_ViewImports.cshtml, die automatisch für jeden View geladen wird.

Listing 1 zeigt Tags mit "asp-" beginnenden Erweiterungsattributen (asp-for, asp-append-version, usw). Microsoft nennt diese Erweiterungsattribute sowie eigenständigen neue Tags wie <environment> und <cache> in Listing 1 "Tag Helper". Sie sind eine elegante Alternative zu den bisherigen HTML Helper-Funktionen (z.B. @Html.TextBoxFor()), die es aber auch weiterhin gibt. Im Einzelnen bieten die in Listing 1 verwendeten Tag Helper folgende Funktionen:
  • asp-for: Datenbindung an ein Property aus dem Modell
  • asp-append-version: Anhängen eines Hash-Wertes für die Datei, der sich jedes Mal ändert, wenn sich die Datei ändert. So wird verhindert, dass der Benutzer wegen Caching im Browser nicht die aktuelle Datei sieht (Cache Busting).
  • <cache>: Zwischenspeicherung des Inhalts für die bei expires-after angegebene Zeitdauer.
  • <environment>: Ausgabe nur, wenn einer der Names genannten Umgebungen aktiv ist. Den Namen für die aktive Umgebung legt man in der Umgebungsvariablen ASPNETCOREENVIRONMENT fest. Mit diesem Tag Helper definiert Microsoft in der Standardlayoutvorlage in der Datei /Shared/Layout.html, dass in den Umgebungen "Staging" und "Produktion", die Bootstrap-CSS-Datei im Standard aus dem Content Delivery Network (CDN) von Microsoft kommt.

Es gibt weitere eingebaute Tag Helper in der Komponente Microsoft.AspNetCore.Mvc.TagHelpers.dll. Damit die Tag Helper überhaupt nutzbar sind, müssen Sie mit @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers eingebunden werden. Dies erledigt Microsoft freundlicherweise in der Projektvorlage schon in der Datei /Shared/_ViewImports.cshtml, die automatisch für jeden View geladen wird.

Listing 1: Eingebaute Tag Helper

@model ITVisions.Autor

<html>

<h3>Autor #@Model.ID: @Model.Name</h3>
<img width="50" src="~/images/Foto_@(Model.Name.Replace(" ","")+".jpg")" asp-append-version="true" />

<input asp-for="Name" class="form-control" />
...

<div>
<cache expires-after="@TimeSpan.FromMinutes(10)">
Zuletzt aktualisiert @DateTime.Now.ToString().
</cache>

Dies ist die
<environment names="development">Entwicklungsumgebung!</environment>
<environment names="test1,test2">Testumgebung!</environment>
<environment names="produktion">Produktionsumgebung!</environment>
</div>

</html>

Eigene Tag Helper

Natürlich kann der Softwareentwickler eigene Tag Helper schreiben. Dazu erstellt er eine öffentliche Klasse, die von Microsoft.AspNetCore.Razor.TagHelpers.TagHelper erbt. Der Name der Klasse sollte konventionsgemäß auf TagHelper enden. Der vordere Teil wird dann zum Tagnamen, wobei Kebab Casing (alias Spinal Casing) Anwendung findet, d.h.
  • Aus der Klasse AutorTagHelper entsteht das Tag <autor>
  • Aus der Klasse DateTimeTagHelper entsteht das Tag <date-time/>

Wenn man einen anderen Tagnamen wünscht oder nicht ein eigenständiges Tag, sondern nur ein neues Attribut für ein bestehendes Tag definieren will, muss man die Annotation [HtmlTargetElement] verwenden.

Eine Tag Helper-Klasse kann öffentliche Properties anbieten, die zu Tag-Attributen werden. Die Klasse überschreibt entweder die Methoden Process() oder ProcessAsync(). Diese Methoden erhalten im Methodenparameter über ein TagHelperContext-Objekt den aktuellen Elementnamen und Taginhalt; sie geben über das ebenfalls per Parameter übergebene Objekt TagHelperOutput den aktualisierten Inhalt zurück.

Die Methodensignatur ist also entweder:
public override void Process(TagHelperContext context, TagHelperOutput output)
{
}
oder:
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
}
Die asynchrone Variante ist aus Gründen der besseren skalierbarkeit zu beveorzugen.

Einbindung der eigenen Tag Helper

Voraussetzung für das Funktionieren aller hier dargestellten Tag Helper ist, dass die Tag Helper mit @addTagHelper einbindet. Wenn die Tag Helper in dem Namensraum ITVisions und in der DLL-Assembly ITVTagHelper liegen, muss die Einbindung so erfolgen:
  • Einzelner Tag Helper

@addTagHelper "ITVisions.AutorTagHelper, ITVTagHelper" eingebunden
  • Alle Tag Helper in einem Namensraum

@addTagHelper "ITVisions*, ITVTagHelper"
@addTagHelper "*, ITVTagHelper"

Beispiel

Listing 2 zeigt das Beispiel des Tag Helpers <Autor>, das ein Autor-Objekt und eine Zahl (Size) als Attribute besitzt und daraus eine Ausgabe in einem HTML-Header-Tag (<h1>, <h2>, <h3> usw.) erzeugt.

Somit kann man nun mit dem neuen Tag Helper anstelle von
<h3>Autor #@Model.ID: @Model.Name</h3>
die gekapselte Form verwenden:
<Autor size="3" autor="Model"></Autor>
sofern man vorher das Tag mit @addTagHelper "ITVisions.AutorTagHelper, ITVTagHelper" eingebunden hat, wobei der erste Parameter der Klassennamen und der zweite Parameter der Assemblyname ist. Anstelle des Klassennamens kann man auch mit * alle Tag Helper einer Assembly einbinden.

Listing 2: Implementierung eines Tag Helpers für das eigene Tag <Autor>

using System;
using WindowsDeveloper;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace ITVisions
{
/// <summary>
/// Tag Helper <Autor autor="objekt" size="zahl 1 bis 5"></Autor>
/// </summary>
public class AutorTagHelper : TagHelper
{
/// <summary>
/// Komplexes Objekt als Parameter
/// </summary>
public Autor Autor { get; set; }
/// <summary>
/// Zahl als Parameter
/// </summary>
public byte Size { get; set; }

public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (Size > 5) Size = 5;
output.TagName = "h" + Size.ToString();
output.Content.SetContent(
$@"Autor #{Autor.ID}: {Autor.Name}");
output.TagMode = TagMode.StartTagAndEndTag;
}
}
}