Introdução aos Ajudantes Personalizados de Marcas em ASP.NET MVC

As aplicações Web modernas exigem código de visualização limpo, mantendível e reutilizável. O ASP.NET Core MVC fornece ajudadores de tags como um poderoso mecanismo de renderização do lado do servidor para transformar e gerar HTML diretamente dentro das visualizações Razor. Enquanto o framework envia com um rico conjunto de ajudadores de tags incorporados para formas, validação, cache e renderização específica do ambiente, projetos do mundo real muitas vezes requerem componentes personalizados que encapsulem padrões de lógica e apresentação específicos de domínio. Criando helpers de tags personalizados permite estender a sintaxe do Razor com seus próprios elementos e atributos HTML, levando a visualizar a composição que é expressiva e consistente.

Ao mover a geração complexa de HTML e a lógica condicional para classes de ajuda de tag reutilizáveis, você separa as preocupações de apresentação da marcação de visualização, melhora a testabilidade e reduz a duplicação em grandes bases de código. Este artigo fornece um guia abrangente para construir ajudantes de tag personalizados em ASP.NET Core MVC, cobrindo tudo, desde a estrutura básica de classe e vinculação de atributos a cenários avançados, como injeção de dependência, processamento assíncrono e componentes de ajuda de tag. Cada seção inclui exemplos práticos e melhores práticas para ajudá-lo a integrar esta técnica ao seu fluxo de trabalho de desenvolvimento diário.

Compreender os Ajudantes de Marcas no Núcleo ASP.NET

Os ajudantes de etiquetas são componentes do lado do servidor que participam na renderização de elementos HTML nas visualizações Razor. Eles permitem que você anexe o código C# a elementos HTML específicos ou nomes de elementos personalizados, transformando a marcação antes de ser enviada ao cliente. Ao contrário dos helpers HTML (que usam chamadas de método como , os ajudantes de etiquetas funcionam combinando com a sintaxe HTML existente, fazendo com que as visualizações se sintam mais naturais para designers e desenvolvedores de front-end.

Por exemplo, o helper de tags incorporado mescla os atributos do controller e da ação no URL correto. Os helpers de tags podem modificar atributos, substituir todo o elemento, adicionar ou remover classes CSS e até injetar HTML adicional. Eles são executados durante o pipeline de execução da visualização Razor e têm acesso total ao contexto atual da solicitação, dados do modelo e serviços registrados.

Modelo de Execução do Servidor-Lado

Quando uma visualização Razor é compilada, os ajudantes de etiquetas são descobertos através de conjuntos e [direções ]. A estrutura avalia cada elemento HTML contra todos os ajudantes de tags registrados, invocando seus métodos ] ou quando uma correspondência é encontrada. Isto acontece antes que o resultado final do HTML seja gerado, permitindo que os ajudantes de tags enriqueçam ou substituam dinamicamente os elementos.

Diferenças de Chaves de Outras Ferramentas de Composição de Vista

  • HTML Helpers: Requer chamadas de método C# dentro de blocos Razor (, que podem quebrar o fluxo HTML-centric. Ajudadores de tags se integram diretamente na sintaxe HTML.
  • Parcials: Bom para reutilizar blocos estáticos de marcação, mas não tem a capacidade de mudar programáticamente a estrutura com base na lógica do lado do servidor sem modelos de visualização adicionais.
  • Ver Componentes: Ideal para widgets complexos e orientados a dados com sua própria lógica e renderização, mas eles requerem uma sintaxe de classe e invocação separada (). Os ajudantes de etiquetas são mais simples para transformações focadas em elementos.

Por que criar ajudantes personalizados de etiquetas?

Embora os ajudantes de tags incorporados cubram muitos cenários comuns, os ajudantes de tags personalizados oferecem vantagens únicas que aumentam diretamente a qualidade do código e a produtividade do desenvolvedor.

  • Encapsular Padrões de Marcação Complexas – Repetir o HTML da caldeira (como componentes estruturados de cartões, tabelas de dados ou botões estilo) pode ser encapsulado em um único elemento personalizado. Alterações propagam-se em toda a aplicação, atualizando uma classe.
  • Enforce Consistência de Design – Um personal ou ajudante de tags pode impor classes CSS consistentes, atributos de acessibilidade e padrões de ligação de dados, reduzindo a chance de inconsistências de UI.
  • Melhorar a legibilidade da visualização – Em vez de aninhar s e blocos condicionais de C#, uma única tag com alguns atributos é muito mais fácil de digitalizar e manter.
  • Ativar o teste unitário da lógica de visualização – Como os ajudantes de tags são classes simples que produzem HTML, você pode escrever testes unitários para verificar a saída gerada para várias entradas, algo difícil de conseguir com código Razor inline.
  • Aumente a reusabilidade em projetos – Uma biblioteca de ajudantes de tag personalizados pode ser empacotada como um componente NuGet e compartilhada em várias soluções, promovendo um kit de ferramentas UI consistente.

Criando um Ajudador de Marcas Personalizado Básico

Cada ajudante de tag personalizado herda da classe (ou implementa diretamente) e é decorado com o atributo para especificar qual elemento HTML ou atributo ele visa. O núcleo da lógica vive dentro do método (ou sua contraparte assíncrona ).

Passo 1: Defina a classe de ajuda de etiquetas

Crie uma nova classe C# em seu projeto, tipicamente dentro de uma pasta . Herdere de e aplique o atributo com o nome do elemento que pretende usar em suas views.

[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>"
 );
 }
}

Passo 2: Compreendendo TagHelperContext e TagHelperOutput

O fornece informações sobre o elemento atual e seus atributos. O permite que você modifique o nome, atributos e conteúdo da tag do elemento. Você também pode usar para texto simples ou para HTML em bruto. Para preservar o conteúdo original (por exemplo, elementos filhos dentro da tag personalizada), você chama como mostrado acima.

Passo 3: Registre o Ajudante de Marcas

Os ajudantes de etiquetas são descobertos automaticamente se estiverem no mesmo conjunto que o aplicativo. Se os seus ajudantes de etiquetas residirem numa biblioteca de classes separada, você deve adicionar uma diretiva em :

@addTagHelper *, MyApp.TagHelpers

O formato é ou um wildcard com para incluir todos os ajudantes de etiquetas desse conjunto. Você também pode usar para excluir ajudantes específicos.

Passo 4: Use o assistente de etiquetas em uma visão Razor

Com o registro no local, você pode usar o elemento personalizado:

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

Isto produz:

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

Técnicas avançadas de ajuda de etiquetas

Usar Atributos e Ligação de Propriedade

Os ajudantes personalizados de etiquetas podem aceitar vários atributos, incluindo tipos complexos e expressões de modelos. Por exemplo, um ajudante de etiquetas que renderize uma entrada de formulário pode vincular uma propriedade a uma expressão de modelo:

[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() ?? "");
 }
}

O atributo ] mapeia a propriedade C# para um nome específico do atributo HTML. Usando dá-lhe acesso aos metadados do modelo para integração completa com validação e lógica de exibição.

Processamento Assíncrono

Se o seu assistente de etiquetas precisar de executar operações de E/S (por exemplo, obter dados de um banco de dados), sobreponha-se a em vez disso:

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

Injecção de dependência em Ajudantes de Marcas

Os ajudantes de etiquetas suportam a injeção do construtor como qualquer outro serviço MVC. Basta adicionar a sua dependência ao construtor e o recipiente DI irá resolvê-lo:

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
 }
}

Note que os ajudantes de tags são transitórios por padrão; uma nova instância é criada para cada uso em uma visualização.

Componentes de Ajudador de Marcas para Injeção Global de HTML

Introduzido no ASP.NET Core 2.1, Os componentes de ajuda de tag permitem que você injecte marcação em todas as respostas globalmente, normalmente usadas para programas, estilos ou análises de agrupamento. Crie uma classe implementando e registre-a em :

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>();

Exemplos práticos para a composição da visão

1. Ajudador de etiqueta condicional do wrapper

Enrole o conteúdo com um elemento adicional apenas se uma condição for cumprida, útil para recipientes de layout responsivo:

[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. Imagem com Carregamento Preguiçoso e Srcset

Crie um ajudante de tags que gera tags responsivas com atributo e múltiplas fontes:

[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. Resumo de validação com estrutura personalizada

Em vez de usar o helper de etiquetas de validação embutido, crie um que adicione ícones personalizados e estilo:

[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());
 }
}

Melhores práticas para a construção de ajudantes de etiquetas

  • Mantenha a lógica C# mínima – Os ajudantes de etiquetas são para transformação de apresentação, não lógica de negócios. Se você precisar de processamento de dados complexo, use um componente de visualização ou serviço.
  • Favor para E/S – Mesmo que sua implementação atual seja síncrona, usar torna mais fácil adicionar chamadas assincronizadas mais tarde sem quebrar as alterações.
  • Use nomes descritivos para elementos personalizados – Siga uma convenção como ou para evitar colisões com futuros padrões HTML.
  • Prenda – Para propriedades internas que não devem ser configuradas a partir de marcação, marque-as com este atributo.
  • Testar o HTML gerado – Escrever testes unitários que instanciam o ajudante de tags, invocar , e verificar a saída usando as asserções .
  • Considere acessibilidade – Adicione atributos ARIA e suporte ao teclado, quando apropriado.

Pistas e solução de problemas comuns

  • O auxiliar de etiquetas não foi descoberto – Certifique-se de que a diretiva em aponta para o conjunto correto. Verifique o espaço de nomes e o nome de classe.
  • Atribuir nomes que não correspondam – Use o atributo para mapear os nomes de propriedades C# para os nomes de atributos HTML. Sem ele, o nome de propriedade é usado como-is.
  • Content not rendering – Se você chamar antes de recuperar conteúdo infantil, você perde o HTML interno original. Sempre ligue primeiro se você precisar.
  • Auxiliadores de etiquetas múltiplas que visam o mesmo elemento – A ordem de execução segue a ordem alfabética por padrão, mas pode ser controlada com a propriedade .
  • Problemas de injeção de dependência – Os ajudantes de etiquetas não são de uma única tonelada. Se você injetar um serviço de escopo, certifique-se de que o auxiliar de tags é consumido dentro do mesmo escopo de solicitação HTTP (normalmente é).

Integrando Ajudantes Personalizados de Marcas em um Codebase existente

A adoção de ajudantes de etiquetas personalizados não requer uma reescrita completa. Você pode começar por refazer os padrões mais repetitivos – como botões, cartões ou tabelas de dados – em ajudantes de etiquetas. Com o tempo, você irá criar uma biblioteca que se torne a única fonte de verdade para seus componentes de UI. Combine helpers de tags com outras ferramentas de composição, como parciais e veja componentes para máxima flexibilidade. Por exemplo, um componente de visualização pode obter dados complexos e então passá- los para um helper de tags para renderizar o HTML final.

Recursos externos e leituras posteriores

Conclusão

Os ajudantes de tag personalizados representam uma evolução significativa na forma como os desenvolvedores compõem visualizações no ASP.NET Core MVC. Ao permitir que você defina seus próprios elementos e atributos HTML que executam a lógica do lado do servidor, eles fazem a ponte entre a marcação amigável ao designer e o programador-controle. De geradores de botões simples a componentes complexos e com conhecimento de estado que se integram com a injeção de dependência, os ajudantes de tags permitem que você construa interfaces de usuário sustentáveis, testáveis e consistentes. Inicie pequeno – refatore um único padrão repetido em um ajudante de tags – e você verá em breve como essa técnica transforma sua camada de visualização para melhor.