Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
Чтобы создать свой tag-хелпер, нам надо унаследовать класс от класса TagHelper, переопределив его метод Process
.
Для примера создадим какой-нибудь простейший тег-хелпер. Допустим, пусть он будет выводить текущее время. Для создания хелпера вначале создадим новый проект ASP.NET Core по типу ASP.NET Core Web App (Model-View-Controller). И затем добавим в него новую папку, которую назовем TagHelpers. Далее в эту папку добавим новый класс TimerTagHelper:
using Microsoft.AspNetCore.Razor.TagHelpers; namespace TagHelpersApp.TagHelpers { public class TimerTagHelper : TagHelper { public override void Process(TagHelperContext context, TagHelperOutput output) { } } }
По умолчанию tag-хелперы применяют соглашения об наименовании, согласно которым класс должен оканчиваться на суффикс TagHelper. Хотя это не является обязательной практикой, мы могли бы определить и просто класс Timer:
public class Timer : TagHelper { }
А вся остальная часть названия, которая идет до TagHelper, будет использоваться в качестве названия тега, то есть <timer>
.
Для генерации элемента html на основе тега используется метод Process. Он принимает два параметра: объект TagHelperContext, представляющий контекст тега (его содержимое, атрибуты), и объект TagHelperOutput, отвечающий за генерацию выходного элемента html на основе тега.
Теперь изменим определение класса следующим образом:
using System; using Microsoft.AspNetCore.Razor.TagHelpers; namespace TagHelpersApp.TagHelpers { public class TimerTagHelper : TagHelper { public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "div"; // заменяет тег <timer> тегом <div> // устанавливаем содержимое элемента output.Content.SetContent($"Текущее время: {DateTime.Now.ToString("HH:mm:ss")}"); } } }
Чтобы задействовать класс хелпера в представлении, нам надо подключить его функциональность в представление. Для этого изменим представление Views/_ViewImports.cshtml следующим образом:
@using TagHelpersApp @using TagHelpersApp.Models @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *, TagHelpersApp
В данном случае предполагается, что проект приложения называется TagHelpersApp. В этом случае первые три директивы должны быть в файле по умолчанию.
Для добавления хелпера используется директива addTagHelper. Директива использует синтаксис подстановочных знаков, определяя, какие tag-хелперы будут загружаться в представление. И также указывается сборка, которая содержит классы хелперы. То есть директива
@addTagHelper *, TagHelpersApp
Здесь первая часть до запятой (в данном случае символ звездочки) указывает, какие tag-хелперы будут загружаться в представление (символ звездочки * используется для загрузки всех хелперов). А вторая часть после запятой указывает на сборку, в которой хранятся хелперы - в данном случае сборка TagHelpersApp (так как хелперы определены в текущем проекте).
Теперь определим в каком-нибудь имеющемся представлении тег:
@{ ViewData["Title"] = "Home Page"; } <timer></timer>
При этом не важно, что он пустой. Можно добавить в него какой-нибудь текст, но он не имеет значение. Главное, что этот тег называется по имени класса без суффикса TagHelper. И в итоге вместо этого тега будет сгенерирован
элемент <div>
, в котором будет выводиться время:
Если в tag-хелпер должен выполнять какие-то асинхронные операции, например, обращаться к базе данных или к файлу в асинхронном режиме, то вместо метода
Process()
мы можем переопределить другой метод класса TagHelper - метод ProcessAsync()
. Например:
using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.TagHelpers; namespace TagHelpersApp.TagHelpers { public class TimerTagHelper : TagHelper { public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "div"; output.Content.SetContent($"Текущее время: {DateTime.Now.ToString("HH:mm:ss")}"); } } public class DateTagHelper : TagHelper { public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "div"; output.Content.SetContent($"Текущая дата: {DateTime.Now.ToString("dd/mm/yyyy")}"); } } public class SummaryTagHelper : TagHelper { public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { output.TagName = "div"; // получаем вложенный контекст из дочерних tag-хелперов var target = await output.GetChildContentAsync(); var content = "<h3>Общая информация</h3>" + target.GetContent(); output.Content.SetHtmlContent(content); } } }
Здесь определены три tag-хелпера. TimerTagHelper и DateTagHelper однотипны, выводят время и дату соответственно. SummaryTagHelper служит как-бы оберткой для обоих хелперов. Предполагается, что TimerTagHelper и DateTagHelper будут вложены в SummaryTagHelper. Например, следующим образом:
<summary> <timer></timer> <date></date> </summary>
В SummaryTagHelper вызывает асинхронный метод output.GetChildContentAsync()
, который возвращает сгенерированную разметку html для вложенных
tag-хелперов. Затем мы можем дополнительно каким-либо образом изменить эту разметку и установить ее в качестве содержимого.
И этот как раз тот случай, когда можно использовать асинхронный метод ProcessAsync.
Если tag-хелпер содержит оба метода: и Process()
, и ProcessAsync()
, то вызываться будет именно метод ProcessAsync()
.