Создание пользовательских тегов в Asp.net Mvc для расширенной композиции просмотра

Введение в пользовательские теги помощников в ASP.NET MVC

Современные веб-приложения требуют чистого, поддерживающегося и многоразового кода просмотра. ASP.NET Core MVC предоставляет помощники тегов в качестве мощного серверного механизма для преобразования и генерации разметки HTML непосредственно в представлениях Razor. В то время как фреймворк поставляется с богатым набором встроенных помощников тегов для форм, проверки, кэширования и рендеринга, ориентированного на среду, проекты в реальном мире часто требуют специализированных компонентов, которые инкапсулируют логику и шаблоны представления, специфичные для домена. Создание помощников тегов позволяет расширить синтаксис Razor с помощью ваших собственных элементов и атрибутов HTML, что приводит к созданию композиции просмотра, которая является одновременно экспрессивной и последовательной.

Перемещая сложное поколение HTML и условную логику в многоразовые классы помощников тегов, вы отделяете проблемы презентации от разметки просмотра, улучшаете проверяемость и уменьшаете дублирование в больших кодовых базах. Эта статья предоставляет всеобъемлющее руководство по созданию пользовательских помощников тегов в ASP.NET Core MVC, охватывая все, от базовой структуры класса и связывания атрибутов до продвинутых сценариев, таких как впрыск зависимости, асинхронная обработка и компоненты помощников тегов. Каждый раздел включает практические примеры и лучшие практики, которые помогут вам интегрировать эту технику в ваш повседневный рабочий процесс разработки.

Понять помощников тегов в ASP.NET Core

Помощники тегов - это серверные компоненты, которые участвуют в рендеринге элементов HTML в представлениях Razor. Они позволяют прикреплять код C# к конкретным элементам HTML или пользовательским именам элементов, преобразуя разметку перед отправкой клиенту. В отличие от помощников HTML (которые используют методы вызовов, такие как ), помощники тегов работают, сопоставляя с существующим синтаксисом HTML, делая представления более естественными для дизайнеров и фронтенд-разработчиков.

Например, встроенный помощник тега объединяет контроллер и атрибуты действия в правильный URL. Помощники тегов могут изменять атрибуты, заменять весь элемент, добавлять или удалять классы CSS и даже вводить дополнительный HTML. Они запускаются во время конвейера выполнения просмотра Razor и имеют полный доступ к текущему контексту запроса, данным модели и зарегистрированным службам.

Модель исполнения Server-Side

Когда скомпилируется представление Razor, помощники тегов обнаруживаются через сборки и директивы . Фреймворк оценивает каждый элемент HTML по всем зарегистрированным помощникам тегов, ссылаясь на их методы или , когда найдено совпадение. Это происходит до того, как генерируется конечный вывод HTML, что позволяет помощникам тегов динамически обогащать или заменять элементы.

Основные отличия от других видов инструментов композиции

Зачем создавать пользовательские помощники тегов?

В то время как встроенные помощники по тегам охватывают многие распространенные сценарии, пользовательские помощники по тегам предоставляют уникальные преимущества, которые непосредственно улучшают качество кода и производительность разработчиков.

Создание базового помощника по пользовательским тегам

Каждый пользовательский помощник тегов наследует от класса (или реализует напрямую) и украшен атрибутом , чтобы указать, какой элемент HTML или атрибут он нацелен.Ядро логики живет внутри метода (или его асинхронного аналога ).

Шаг 1: Определите класс помощников по тегам

Создайте новый класс C# в своем проекте, как правило, внутри папки . Наследуйте от и примените атрибут с именем элемента, которое вы намерены использовать в своих представлениях.

[HtmlTargetElement("custom-card")]
public class CustomCardTagHelper : TagHelper
{
 public string Title { get; set; }
 public string CssClass { get; set; } = "card-default";

 public override void Process(TagHelperContext context, TagHelperOutput output)
 {
 // Replace the custom tag with a div and add the desired structure
 output.TagName = "div";
 output.Attributes.SetAttribute("class", $"card {CssClass}");

 // Build inner content
 output.Content.SetHtmlContent(
 $@"<div class=""card-header"">{Title}</div>
 <div class=""card-body"">
 {output.Content.GetContent()}
 </div>"
 );
 }
}

Шаг 2: Понимание TagHelperContext и TagHelperOutput

предоставляет информацию о текущем элементе и его атрибутах. позволяет изменять имя, атрибуты и контент элемента. также можно использовать для простого текста или для исходного HTML. Для сохранения исходного контента (например, детских элементов в пользовательском теге), вы звоните , как показано выше.

Шаг 3: Зарегистрируйте помощника по тегам

Если помощники по тегу находятся в той же сборке, что и приложение, если помощники по тегу находятся в отдельной библиотеке классов, вы должны добавить директиву в :

@addTagHelper *, MyApp.TagHelpers

Формат или wildcard с , чтобы включить всех помощников тегов из этой сборки. также можно использовать, чтобы исключить конкретных помощников.

Шаг 4: Используйте тег-помощник в бритвенном виде

С регистрацией на месте вы можете использовать пользовательский элемент:

<custom-card title="Welcome" css-class="card-primary">
 This is the body content
</custom-card>

Это приводит к:

<div class="card card-primary">
 <div class="card-header">Welcome</div>
 <div class="card-body">
 This is the body content
 </div>
</div>

Advanced Tag Helper Techniques (Техника помощи)

Использование атрибутов и свойств, связывающих

Помощники по пользовательскому тегу могут принимать несколько атрибутов, включая сложные типы и выражения моделей. Например, помощник по тегу, который отображает ввод формы, может связывать свойство с выражением модели:

[HtmlTargetElement("email-input")]
public class EmailInputTagHelper : TagHelper
{
 [HtmlAttributeName("asp-for")]
 public ModelExpression For { get; set; }

 public override void Process(TagHelperContext context, TagHelperOutput output)
 {
 output.TagName = "input";
 output.Attributes.SetAttribute("type", "email");
 output.Attributes.SetAttribute("id", For.Name);
 output.Attributes.SetAttribute("name", For.Name);
 output.Attributes.SetAttribute("value", For.Model?.ToString() ?? "");
 }
}

атрибут отображает свойство C# на конкретное имя атрибута HTML. Использование даёт вам доступ к метаданным модели для полной интеграции с валидацией и логикой отображения.

Асинхронная обработка

Если ваш помощник по тегу должен выполнять операции ввода/вывода (например, извлекать данные из базы данных), вместо этого переопределите :

public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
 var data = await _someService.GetDataAsync();
 output.Content.SetHtmlContent(data);
}

Инъекция зависимостей в Tag Helpers

Тег-помощники поддерживают инъекцию конструктора, как и любой другой сервис MVC. Просто добавьте свою зависимость от конструктора, и контейнер DI решит ее:

public class UserProfileTagHelper : TagHelper
{
 private readonly IUserService _userService;

 public UserProfileTagHelper(IUserService userService)
 {
 _userService = userService;
 }

 public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
 {
 var user = await _userService.GetCurrentUserAsync();
 // render user profile markup
 }
}

Обратите внимание, что помощники по тегам являются временными по умолчанию; для каждого использования в представлении создается новый экземпляр.

Компоненты-помощники для глобальной HTML-инъекции

Введенные в ASP.NET Core 2.1, Tag Helper Components позволяют вводить разметку в каждый ответ по всему миру, обычно используемый для объединения скриптов, стилей или аналитики. Создать класс, реализующий и зарегистрировать его в :

public class GlobalScriptTagHelperComponent : TagHelperComponent
{
 public override void Process(TagHelperContext context, TagHelperOutput output)
 {
 if (output.TagName == "body" && output.Attributes.ContainsName("data-scripts"))
 {
 output.PostContent.AppendHtml("<script src='/js/global.js'></script>");
 }
 }
}

// In Startup.ConfigureServices
services.AddTransient<ITagHelperComponent, GlobalScriptTagHelperComponent>();

Практические примеры для просмотра композиции

1.Условный помощник Wrapper Tag

Обертывающее содержимое с дополнительным элементом только при условии выполнения условия, полезное для адаптивной компоновки контейнеров:

[HtmlTargetElement("if-wrapper")]
public class IfWrapperTagHelper : TagHelper
{
 public bool Condition { get; set; }

 public override void Process(TagHelperContext context, TagHelperOutput output)
 {
 if (!Condition)
 {
 // Remove the wrapping element, output only the child content
 output.TagName = null;
 output.Content.SetContent(output.Content.GetContent());
 }
 else
 {
 output.TagName = "div";
 output.Attributes.SetAttribute("class", "wrapper");
 }
 }
}

2. Изображение с ленивой нагрузкой и сксетом

Создайте помощника, который генерирует теги с атрибутом и несколькими источниками:

[HtmlTargetElement("lazy-image")]
public class LazyImageTagHelper : TagHelper
{
 public string Src { get; set; }
 public string Srcset { get; set; }
 public string Alt { get; set; }
 public string CssClass { get; set; }

 public override void Process(TagHelperContext context, TagHelperOutput output)
 {
 output.TagName = "img";
 output.Attributes.SetAttribute("src", Src);
 if (!string.IsNullOrEmpty(Srcset))
 output.Attributes.SetAttribute("srcset", Srcset);
 output.Attributes.SetAttribute("alt", Alt);
 output.Attributes.SetAttribute("loading", "lazy");
 if (!string.IsNullOrEmpty(CssClass))
 output.Attributes.SetAttribute("class", CssClass);
 }
}

3. Резюме валидации с использованием пользовательской структуры

Вместо того, чтобы использовать встроенный помощник проверки тегов, создайте тот, который добавляет пользовательские значки и стиль:

[HtmlTargetElement("custom-validation-summary")]
public class CustomValidationSummaryTagHelper : TagHelper
{
 [HtmlAttributeName("asp-validation-summary")]
 public ValidationSummary ValidationSummary { get; set; }

 [ViewContext]
 public ViewContext ViewContext { get; set; }

 public override void Process(TagHelperContext context, TagHelperOutput output)
 {
 var viewData = ViewContext.ViewData;
 var errors = viewData.ModelState.Where(s => s.Value.Errors.Count > 0).SelectMany(s => s.Value.Errors).ToList();

 if (errors.Count == 0)
 {
 output.SuppressOutput();
 return;
 }

 output.TagName = "div";
 output.Attributes.SetAttribute("class", "alert alert-danger");
 var list = new StringBuilder();
 list.Append("<ul class='mb-0'>");
 foreach (var error in errors)
 {
 list.Append($"<li><strong>Error:</strong> {error.ErrorMessage}</li>");
 }
 list.Append("</ul>");
 output.Content.SetHtmlContent(list.ToString());
 }
}

Лучшие практики для создания тегов

Общие подводные камни и устранение неполадок

  • Не обнаруженный помощник тега — Убедитесь, что директива указывает на правильную сборку.
  • Имена атрибутов, не соответствующие — Используйте атрибут для отображения имен свойств C# на имена атрибутов HTML.
  • Контент не отображает — Если вы звоните перед извлечением содержимого для ребенка, вы теряете исходный внутренний HTML.
  • Множественные помощники тегов, нацеленные на один и тот же элемент — Порядок выполнения по умолчанию следует алфавитному порядку, но может управляться свойством .
  • Проблемы с инъекцией зависимости — помощники тегов не ограничены одним тегом. Если вы вводите ограниченный сервис, убедитесь, что помощник тега потребляется в том же объеме HTTP-запроса (обычно это так).

Интеграция пользовательских помощников тегов в существующую кодовую базу

Принятие пользовательских помощников тегов не требует полного переписывания. Вы можете начать с рефакторинга самых повторяющихся шаблонов - таких как кнопки, карты или таблицы данных - в помощники тегов. Со временем вы создадите библиотеку, которая станет единственным источником истины для ваших компонентов пользовательского интерфейса. объедините помощников тегов с другими инструментами композиции, такими как части и компоненты просмотра, для максимальной гибкости. Например, компонент просмотра может получать сложные данные, а затем передать его помощнику тегов для рендеринга окончательного HTML.

Внешние ресурсы и дальнейшее чтение

Заключение

Пользовательские помощники тегов представляют собой значительную эволюцию в том, как разработчики составляют представления в ASP.NET Core MVC. Позволив вам определить свои собственные элементы HTML и атрибуты, которые выполняют логику на стороне сервера, они преодолевают разрыв между удобной для дизайнера разметкой и управлением программистом. От простых генераторов кнопок до сложных, известных государству компонентов, которые интегрируются с впрыском зависимости, помощники тегов позволяют вам создавать поддерживаемые, тестируемые и последовательные пользовательские интерфейсы. Начните с малого - перефактор один повторяющийся шаблон в помощник тегов - и вы скоро увидите, как эта техника преобразует ваш слой просмотра в лучшую сторону.