Чтобы создать свой tag-хелпер, нам надо унаследовать класс от класса TagHelper, переопределив его метод Process или ProcessAsync().
Для примера создадим какой-нибудь простейший тег-хелпер. Допустим, пусть он будет выводить текущее время. Для создания хелпера вначале добавим в проект новую папку, которую назовем TagHelpers. Далее в эту папку добавим новый класс TimerTagHelper:
using Microsoft.AspNetCore.Razor.TagHelpers; namespace MvcApp.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 Microsoft.AspNetCore.Razor.TagHelpers; namespace MvcApp.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")}"); } } }
Чтобы задействовать класс хелпера в представлении, нам надо подключить его функциональность в представление следующим образом:
@addTagHelper *, MvcApp
В данном случае предполагается, что проект приложения называется MvcApp. Для добавления хелпера используется директива addTagHelper. Директива использует синтаксис подстановочных знаков, определяя, какие tag-хелперы будут загружаться в представление. И также указывается сборка, которая содержит классы хелперы. То в директиве
@addTagHelper *, MvcApp
первая часть до запятой (в данном случае символ звездочка) указывает, какие tag-хелперы будут загружаться в представление (символ звездочки * используется для загрузки всех хелперов). А вторая часть после запятой указывает на сборку, в которой хранятся хелперы - в данном случае сборка MvcApp (так как хелперы определены в текущем проекте).
Если представления использует файл _ViewImports.cshtml, то данную директиву можно определить в _ViewImports.cshtml, чтобы подключить хелпер сразу во все представления.
Теперь используем выше определенный tag-хелпер TimerTagHelper в каком-нибудь представлении:
@addTagHelper *, MvcApp <timer></timer>
При этом не важно, что элемент <timer>
пустой. Можно добавить в него какой-нибудь текст, но он не имеет значение. Главное, что этот тег называется по имени класса без суффикса TagHelper. И в итоге вместо этого тега будет сгенерирован
элемент <div>
, в котором будет выводиться время:
Если в tag-хелпер должен выполнять какие-то асинхронные операции, например, обращаться к базе данных или к файлу в асинхронном режиме, то вместо метода
Process()
мы можем переопределить другой метод класса TagHelper - метод ProcessAsync()
. Например:
using Microsoft.AspNetCore.Razor.TagHelpers; namespace MvcApp.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. Например, следующим образом:
@addTagHelper *, MvcApp <summary> <timer></timer> <date></date> </summary>
В SummaryTagHelper вызывает асинхронный метод output.GetChildContentAsync()
, который возвращает сгенерированную разметку html для вложенных
tag-хелперов. Затем мы можем дополнительно каким-либо образом изменить эту разметку и установить ее в качестве содержимого.
И этот как раз тот случай, когда можно использовать асинхронный метод ProcessAsync.
Если tag-хелпер содержит оба метода: и Process()
, и ProcessAsync()
, то вызываться будет именно метод ProcessAsync()
.