Eigene Tag Helper für ASP.NET Core schreiben

Kolumne: .NETversum

Kolumne: .NETversum

Eigene Tag Helper für ASP.NET Core schreiben

Kolumne: .NETversum


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 MVC) oder in Pages (bei ASP.NET Core Razor Pages) einsetzen.

Das ist vergleichbar mit 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 Web Forms, sind aber in ihrer Implementierung wesentlich einfacher. Eine Entwurfszeitansicht gibt es hier nicht. Tag Helper können sich auch auf Standard-HTML-Tags beziehen und sie modifizieren.

Tag Helper für ein .NET-Objekt

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

Listing 1: Implementierung eines Tag Helpers für den eigenen Tag <Autor>

using Microsoft.AspNetCore.Razor.TagHelpers;
 
namespace ITVisions
{
  /// <summary>
  /// Tag Helper
  /// Verwendung: <Autor autor="objekt" size="zahl   /// 1 bis 5"></Autor>
  /// </summary>
  public class AutorTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.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;
    }
  }
}

Man kann 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 Klassenname und der zweite Parameter der Assembly-Name ist. Anstelle des Klassennamens kann man auch mit * alle Tag Helper einer Assembly einbinden.

Tag Helper für wiederholte Ausgabe

Mit Tag Helpern kann man das Repeater-Steuerelement aus ASP.NET Web Forms nachbauen. Der Trick ist, dass man ProcessAsync() verwendet, dass erlaubt, beliebige Inhalte im Tag mit GetChildContentAsync() wieder zu rendern. Auch Tag Helper können wieder im Inhalt enthalten sein (Listing 2).

Listing 2: Tag Helper <repeater>

using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Threading.Tasks;
 
namespace ITVisions
{
  /// <summary>
  /// x Wiederholungen des Kindinhaltes
  /// </summary>
  public class RepeaterTagHelper : TagHelper
  {
    public int Count { get; set; }
 
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
      output.TagName = null;
      for (int i = 0; i <= Count; i++)
      {
        var e = await output.GetChildContentAsync(useCachedResult: false);
        output.Content.AppendHtml(e.GetContent());
      }
    }
  }
}

Beim Beispiel in Listing 3 kommen zwei Tag-Helper-Attribute fett und kursiv zum Einsatz. Den Einsatz eines Tag Helpers mit untergeordneten Tag Helpern zeigt Listing 4. Die geraden Jahre werden fett dargestellt, die ungeraden kursiv.

Listing 3: Tag-Helper-Attribute für fett und kursiv

using Microsoft.AspNetCore.Razor.TagHelpers;
 
namespace ITVisions
{
  [HtmlTargetElement(Attributes = "fett")]
  public class FettTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
  {
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
      output.Attributes.RemoveAll("fett");
      output.Attributes.Add("style","font-weight:bold");
      //oder: 
      //output.PreContent.SetHtmlContent(“<strong>”);
      //output.PostContent.SetHtmlContent(“</strong>”);
    }
  }
  
  [HtmlTargetElement(Attributes = "kursiv")]
  public class Italic : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper
  {
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
      output.Attributes.RemoveAll("kursiv");
      output.Attributes.Add("style", "font-style:italic");
      //oder: 
      //output.PreContent.SetHtmlContent(“<i>”);
      //output.PostContent.SetHtmlContent(“</i>”);
    }
  }
}

Listing 4: Einsatz von <repeater>

<p>Repeater:</p>
@{
  int jahr = DateTime.Now.Year;
}
<ul>
  <repeater count="5">
    @if (jahr % 2 == 0)
    {
      <li fett>Jahr @(jahr++) </li>
    }
    else
    {
      <li kursiv>Jahr @(jahr++) </li>
    }
  </repeater>
</ul>

Tag Helper für bedingte Ausgabe

Der Tag Helper in Listing 5 zeigt, wie man Inhalte beim Rendern via SuppressOutput() leicht mit einem eigenen Tag-Helper-Attribut unterdrückt, das man in jedes beliebige Attribut einbauen kann. Alle Tag-Helper-Parameter, die nicht vom Typ string sind, werden beim Aufruf als Ausdrücke behandelt – auch ohne Razor-Syntax mit @!.

Listing 5: Tag-Helper-Attribut Condition

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Runtime.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
 
namespace ITVisions
{
  [HtmlTargetElement(Attributes = nameof(Condition))]
  public class ConditionTagHelper : TagHelper
  {
    public bool Condition { get; set; }
 
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
      if (!Condition)
      {
        output.SuppressOutput();
      }
    }
  }
}

schwichtenberg_holger_dr_sw.tif_fmt1.jpgDr. Holger Schwichtenberg (MVP) – alias „Der DOTNET-DOKTOR“ – gehört zu den bekanntesten .NET-Experten in Deutschland. Er ist Entwicklungsleiter der 5Minds IT-Solutions GmbH & Co. KG. Zudem unterstützt er mit seiner Firma www.IT-Visions.de kleine und große Unternehmen durch Beratung und Schulung bei der Erstellung von Windows- und webbasierten .NET-Anwendungen. Seit 1998 ist er ununterbrochen Sprecher auf jeder BASTA und Autor zahlreicher Fachbücher.

Mail Web
Holger Schwichtenberg

Dr. Holger Schwichtenberg - alias der "DOTNET-DOKTOR" - ist technischer Leiter des Expertennetzwerks www.IT-Visions.de, das mit 53 renommierten Experten zahlreiche mittlere und große Unternehmen durch Beratungen und Schulungen sowie bei der Softwareentwicklung unterstützt. Seine persönlichen Tätigkeitsschwerpunkte sind Webanwendungen, verteilte Systeme, systemnahe Programmierung und Datenbankzugriffe. Er programmiert leidenschaftlich in C# und JavaScript/TypeScript sowie PowerShell. Durch seine Auftritte auf zahlreichen nationalen und internationalen Fachkonferenzen sowie mehr als 90 Fachbücher für O’Reilly, Addison-Wesley, Microsoft Press und dem Hanser-Verlag gehört er zu den bekanntesten Softwareentwicklungsexperten in Deutschland. Darüber hinaus ist er ständiger Mitarbeiter bei Windows Developer und anderen Fachzeitschriften. Er hat in seiner Karriere bereits über 1500 Fachartikel veröffentlicht. Von Microsoft wird er für sein .NET-Fachwissen seit nunmehr 20 Jahren als Microsoft Most Valuable Professional (MVP) ausgezeichnet. Zudem ist er seit 1999 durchgehend Sprecher auf jeder BASTA!-Konferenz.