Componentes del asistente de etiquetas en ASP.NET Core
Por Scott Addie y Fiyaz Bin Hasan
El componente de un asistente de etiquetas es un asistente de etiquetas que permite modificar o agregar con condiciones elementos HTML a partir del código del lado servidor. Esta característica está disponible en ASP.NET Core 2.0 o versiones posteriores.
ASP.NET Core incluye dos componentes de asistente de etiquetas integrados: head
y body
. Se encuentran en el espacio de nombres Microsoft.AspNetCore.Mvc.Razor.TagHelpers y pueden usarse tanto en MVC como en Razor Pages. Los componentes de asistente de etiquetas no requieren el registro en la aplicación en _ViewImports.cshtml
.
Vea o descargue el código de ejemplo (cómo descargarlo)
Casos de uso
Dos casos de uso comunes de componentes de asistente de etiquetas incluyen:
En las secciones siguientes se describen estos casos de uso.
Insertar en el elemento de encabezado HTML
Dentro del elemento <head>
HTML, los archivos CSS suelen importarse con el elemento <link>
HTML. El código siguiente inserta un elemento <link>
en el elemento <head>
con el componente de asistente de etiquetas head
:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace RazorPagesSample.TagHelpers
{
public class AddressStyleTagHelperComponent : TagHelperComponent
{
private readonly string _style =
@"<link rel=""stylesheet"" href=""/css/address.css"" />";
public override int Order => 1;
public override Task ProcessAsync(TagHelperContext context,
TagHelperOutput output)
{
if (string.Equals(context.TagName, "head",
StringComparison.OrdinalIgnoreCase))
{
output.PostContent.AppendHtml(_style);
}
return Task.CompletedTask;
}
}
}
En el código anterior:
AddressStyleTagHelperComponent
implementa TagHelperComponent. La abstracción:- Permite la inicialización de la clase con TagHelperContext.
- Permite usar componentes de asistente de etiquetas para agregar o modificar elementos HTML.
- La propiedad Order define el orden en el que se representan los componentes.
Order
es necesario cuando hay varios usos de los componentes de asistente de etiquetas en una aplicación. - ProcessAsync compara el valor de propiedad TagName del contexto de ejecución con
head
. Si la comparación se evalúa como true, el contenido del campo_style
se inserta en el elemento<head>
HTML.
Insertar en el elemento del cuerpo HTML
El componente de asistente de etiquetas body
puede insertar un elemento <script>
en el elemento <body>
. El código siguiente demuestra esta técnica:
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace RazorPagesSample.TagHelpers
{
public class AddressScriptTagHelperComponent : TagHelperComponent
{
public override int Order => 2;
public override async Task ProcessAsync(TagHelperContext context,
TagHelperOutput output)
{
if (string.Equals(context.TagName, "body",
StringComparison.OrdinalIgnoreCase))
{
var script = await File.ReadAllTextAsync(
"TagHelpers/Templates/AddressToolTipScript.html");
output.PostContent.AppendHtml(script);
}
}
}
}
Se usa un archivo HTML independiente para almacenar el elemento <script>
. El archivo HTML hace que el código sea más limpio y más fácil de mantener. El código anterior lee el contenido de TagHelpers/Templates/AddressToolTipScript.html
y lo anexa con la salida del asistente de etiquetas. El archivo AddressToolTipScript.html
incluye el marcado siguiente:
<script>
$("address[printable]").hover(function() {
$(this).attr({
"data-toggle": "tooltip",
"data-placement": "right",
"title": "Home of Microsoft!"
});
});
</script>
El código anterior enlaza un widget de información sobre herramientas de arranque a cualquier elemento <address>
que incluye un atributo printable
. El efecto es visible cuando el puntero del mouse se sitúa sobre el elemento.
Registro de un componente
Se debe agregar un componente de asistente de etiquetas a la colección de componentes de asistente de etiquetas de la aplicación. Hay tres maneras de agregarlo a la colección:
- Registro mediante el contenedor de servicios
- Registro mediante un archivo de Razor
- Registro con el modelo de página o controlador
Registro mediante el contenedor de servicios
Si la clase de componente de asistente de etiquetas no se administran con ITagHelperComponentManager, se debe registrar con el sistema de inserción de dependencias (DI). El código Startup.ConfigureServices
siguiente registra las clases AddressStyleTagHelperComponent
y AddressScriptTagHelperComponent
con una duración transitoria:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddTransient<ITagHelperComponent,
AddressScriptTagHelperComponent>();
services.AddTransient<ITagHelperComponent,
AddressStyleTagHelperComponent>();
}
Registro mediante un archivo de Razor
Si el componente de asistente de etiquetas no está registrado con la inserción de dependencias, se puede registrar desde una página de Razor Pages o desde una vista de MVC. Esta técnica se usa para controlar el orden de ejecución del componente y el marcado insertado desde un archivo de Razor.
ITagHelperComponentManager
se usa para agregar componentes de asistente de etiquetas o para quitarlos de la aplicación. El código siguiente demuestra esta técnica con AddressTagHelperComponent
:
@using RazorPagesSample.TagHelpers;
@using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
@inject ITagHelperComponentManager manager;
@{
string markup;
if (Model.IsWeekend)
{
markup = "<em class='text-warning'>Office closed today!</em>";
}
else
{
markup = "<em class='text-info'>Office open today!</em>";
}
manager.Components.Add(new AddressTagHelperComponent(markup, 1));
}
En el código anterior:
- La directiva
@inject
proporciona una instancia deITagHelperComponentManager
. La instancia está asignada a una variable denominadamanager
para el acceso descendente en el archivo de Razor. - Se agrega una instancia de
AddressTagHelperComponent
a la colección de componentes de asistente de etiquetas de la aplicación.
AddressTagHelperComponent
se modifica para alojar un constructor que acepta los parámetros markup
y order
:
private readonly string _markup;
public override int Order { get; }
public AddressTagHelperComponent(string markup = "", int order = 1)
{
_markup = markup;
Order = order;
}
El parámetro markup
proporcionado se utiliza en ProcessAsync
como sigue:
public override async Task ProcessAsync(TagHelperContext context,
TagHelperOutput output)
{
if (string.Equals(context.TagName, "address",
StringComparison.OrdinalIgnoreCase) &&
output.Attributes.ContainsName("printable"))
{
TagHelperContent childContent = await output.GetChildContentAsync();
string content = childContent.GetContent();
output.Content.SetHtmlContent(
$"<div>{content}<br>{_markup}</div>{_printableButton}");
}
}
Registro con el modelo de página o controlador
Si el componente de asistente de etiquetas no está registrado con la inserción de dependencias, se puede registrar desde un modelo de página de Razor Pages o desde un controlador de MVC. Esta técnica es útil para separar la lógica de C# de archivos de Razor.
La inserción del constructor se utiliza para acceder a una instancia de ITagHelperComponentManager
. El componente de asistente de etiquetas se agrega a la colección de componentes de asistente de etiquetas de la instancia. El modelo de página de Razor Pages siguiente muestra esta técnica con AddressTagHelperComponent
:
using System;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.RazorPages;
using RazorPagesSample.TagHelpers;
public class IndexModel : PageModel
{
private readonly ITagHelperComponentManager _tagHelperComponentManager;
public bool IsWeekend
{
get
{
var dayOfWeek = DateTime.Now.DayOfWeek;
return dayOfWeek == DayOfWeek.Saturday ||
dayOfWeek == DayOfWeek.Sunday;
}
}
public IndexModel(ITagHelperComponentManager tagHelperComponentManager)
{
_tagHelperComponentManager = tagHelperComponentManager;
}
public void OnGet()
{
string markup;
if (IsWeekend)
{
markup = "<em class='text-warning'>Office closed today!</em>";
}
else
{
markup = "<em class='text-info'>Office open today!</em>";
}
_tagHelperComponentManager.Components.Add(
new AddressTagHelperComponent(markup, 1));
}
}
En el código anterior:
- La inserción del constructor se utiliza para acceder a una instancia de
ITagHelperComponentManager
. - Se agrega una instancia de
AddressTagHelperComponent
a la colección de componentes de asistente de etiquetas de la aplicación.
Creación de un componente
Para crear un componente de asistente de etiquetas personalizado:
- Cree una clase pública derivada de TagHelperComponentTagHelper.
- Aplique el atributo
[HtmlTargetElement]
a la clase. Especifique el nombre del elemento HTML de destino. - Opcionalmente: aplique el atributo
[EditorBrowsable(EditorBrowsableState.Never)]
a la clase para suprimir la presentación del tipo en IntelliSense.
El código siguiente crea un componente de asistente de etiquetas personalizado que tiene como destino el elemento <address>
HTML:
using System.ComponentModel;
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Logging;
namespace RazorPagesSample.TagHelpers
{
[HtmlTargetElement("address")]
[EditorBrowsable(EditorBrowsableState.Never)]
public class AddressTagHelperComponentTagHelper : TagHelperComponentTagHelper
{
public AddressTagHelperComponentTagHelper(
ITagHelperComponentManager componentManager,
ILoggerFactory loggerFactory) : base(componentManager, loggerFactory)
{
}
}
}
Use el componente de asistente de etiquetas address
personalizado para insertar el marcado HTML como sigue:
public class AddressTagHelperComponent : TagHelperComponent
{
private readonly string _printableButton =
"<button type='button' class='btn btn-info' onclick=\"window.open(" +
"'https://binged.it/2AXRRYw')\">" +
"<span class='glyphicon glyphicon-road' aria-hidden='true'></span>" +
"</button>";
public override int Order => 3;
public override async Task ProcessAsync(TagHelperContext context,
TagHelperOutput output)
{
if (string.Equals(context.TagName, "address",
StringComparison.OrdinalIgnoreCase) &&
output.Attributes.ContainsName("printable"))
{
var content = await output.GetChildContentAsync();
output.Content.SetHtmlContent(
$"<div>{content.GetContent()}</div>{_printableButton}");
}
}
}
El método ProcessAsync
anterior inserta el elemento HTML proporcionado a SetHtmlContent en el elemento <address>
coincidente. La inserción se produce cuando:
- El valor de propiedad
TagName
del contexto de ejecución es igual aaddress
. - El elemento
<address>
correspondiente tiene un atributoprintable
.
Por ejemplo, la instrucción if
se evalúa como true al procesar el siguiente elemento <address>
:
<address printable>
One Microsoft Way<br />
Redmond, WA 98052-6399<br />
<abbr title="Phone">P:</abbr>
425.555.0100
</address>
Recursos adicionales
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente GitHub Issues como mecanismo de comentarios sobre el contenido y lo sustituiremos por un nuevo sistema de comentarios. Para más información, vea:Enviar y ver comentarios de