Kolumne: .NETversum

Eigene Tag Helper für ASP.NET Core schreiben

Eigene Tag Helper für ASP.NET Core schreiben

Kolumne: .NETversum

Eigene Tag Helper für ASP.NET Core schreiben


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


Repeater:
@{
  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();
      }
    }
  }
}

 

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.


Weitere Artikel zu diesem Thema