Componentes de vista en ASP.NET CoreView components in ASP.NET Core

Por Rick AndersonBy Rick Anderson

Vea o descargue el código de ejemplo (cómo descargarlo)View or download sample code (how to download)

Componentes de vistaView components

Los componentes de vista son similares a las vistas parciales, pero mucho más eficaces.View components are similar to partial views, but they're much more powerful. Los componentes de vista no usan el enlace de modelos y solo dependen de los datos proporcionados cuando se les llama.View components don't use model binding, and only depend on the data provided when calling into it. Este artículo se escribió en torno a ASP.NET Core MVC, pero los componentes de vista también funcionan con páginas de Razor.This article was written using ASP.NET Core MVC, but view components also work with Razor Pages.

Un componente de vista:A view component:

  • Representa un fragmento en lugar de una respuesta completa.Renders a chunk rather than a whole response.
  • Incluye las mismas ventajas de separación de conceptos y capacidad de prueba que se encuentran entre un controlador y una vista.Includes the same separation-of-concerns and testability benefits found between a controller and view.
  • Puede tener parámetros y lógica de negocios.Can have parameters and business logic.
  • Normalmente se invoca desde una página de diseño.Is typically invoked from a layout page.

Los componentes de vista están diseñados para cualquier lugar que tenga lógica de representación reutilizable demasiado compleja para una vista parcial, como:View components are intended anywhere you have reusable rendering logic that's too complex for a partial view, such as:

  • Menús de navegación dinámicaDynamic navigation menus
  • Nube de etiquetas (donde consulta la base de datos)Tag cloud (where it queries the database)
  • Panel de inicio de sesiónLogin panel
  • Carro de la compraShopping cart
  • Artículos publicados recientementeRecently published articles
  • Contenido de la barra lateral de un blog típicoSidebar content on a typical blog
  • Un panel de inicio de sesión que se representa en cada página y muestra los vínculos para iniciar o cerrar sesión, según el estado del usuarioA login panel that would be rendered on every page and show either the links to log out or log in, depending on the log in state of the user

Un componente de vista consta de dos partes: la clase (normalmente derivada de ViewComponent) y el resultado que devuelve (por lo general, una vista).A view component consists of two parts: the class (typically derived from ViewComponent) and the result it returns (typically a view). Al igual que los controladores, un componente de vista puede ser un POCO, pero la mayoría de los desarrolladores prefieren aprovechar las ventajas que ofrecen los métodos y las propiedades disponibles al derivar de ViewComponent.Like controllers, a view component can be a POCO, but most developers will want to take advantage of the methods and properties available by deriving from ViewComponent.

Crear un componente de vistaCreating a view component

Esta sección contiene los requisitos de alto nivel para crear un componente de vista.This section contains the high-level requirements to create a view component. Más adelante en el artículo examinaremos cada paso en detalle y crearemos un componente de vista.Later in the article, we'll examine each step in detail and create a view component.

La clase de componente de vistaThe view component class

Es posible crear una clase de componente de vista mediante una de las siguientes acciones:A view component class can be created by any of the following:

  • Derivar de ViewComponentDeriving from ViewComponent
  • Decorar una clase con el atributo [ViewComponent] o derivar de una clase con el atributo [ViewComponent]Decorating a class with the [ViewComponent] attribute, or deriving from a class with the [ViewComponent] attribute
  • Crear una clase cuyo nombre termina con el sufijo ViewComponentCreating a class where the name ends with the suffix ViewComponent

Al igual que los controladores, los componentes de vista deben ser clases públicas, no anidadas y no abstractas.Like controllers, view components must be public, non-nested, and non-abstract classes. El nombre del componente de vista es el nombre de la clase sin el sufijo "ViewComponent".The view component name is the class name with the "ViewComponent" suffix removed. También se puede especificar explícitamente mediante la propiedad ViewComponentAttribute.Name.It can also be explicitly specified using the ViewComponentAttribute.Name property.

Una clase de componente de vista:A view component class:

  • Es totalmente compatible con la inserción de dependencias de constructor.Fully supports constructor dependency injection

  • No participa en el ciclo de vida del controlador, lo que significa que no se pueden usar filtros en un componente de vista.Doesn't take part in the controller lifecycle, which means you can't use filters in a view component

Métodos de componente de vistaView component methods

Un componente de vista define su lógica en un método InvokeAsync que devuelve IViewComponentResult.A view component defines its logic in an InvokeAsync method that returns an IViewComponentResult. Los parámetros proceden directamente de la invocación del componente de vista, no del enlace de modelos.Parameters come directly from invocation of the view component, not from model binding. Un componente de vista nunca controla directamente una solicitud.A view component never directly handles a request. Por lo general, un componente de vista inicializa un modelo y lo pasa a una vista mediante una llamada al método View.Typically, a view component initializes a model and passes it to a view by calling the View method. En resumen, los métodos de componente de vista:In summary, view component methods:

  • Definen un método InvokeAsync que devuelve IViewComponentResult.Define an InvokeAsync method that returns an IViewComponentResult
  • Por lo general, inicializan un modelo y lo pasan a una vista mediante una llamada al método ViewComponent View.Typically initializes a model and passes it to a view by calling the ViewComponent View method
  • Los parámetros provienen del método que realiza la llamada, y no de HTTP, ya que no hay ningún enlace de modelos.Parameters come from the calling method, not HTTP, there's no model binding
  • No son accesibles directamente como un punto de conexión HTTP, sino que se invocan desde el código (normalmente en una vista).Are not reachable directly as an HTTP endpoint, they're invoked from your code (usually in a view). Un componente de vista nunca controla una solicitud.A view component never handles a request
  • Se sobrecargan en la firma, en lugar de los detalles de la solicitud HTTP actual.Are overloaded on the signature rather than any details from the current HTTP request

Ruta de búsqueda de la vistaView search path

El tiempo de ejecución busca la vista en las rutas de acceso siguientes:The runtime searches for the view in the following paths:

  • /Pages/Components/{Nombre de componente de vista}/{Nombre de vista}/Pages/Components/{View Component Name}/{View Name}
  • /Views/{Controller Name}/Components/{Nombre de componente de vista}/{Nombre de vista}/Views/{Controller Name}/Components/{View Component Name}/{View Name}
  • /Views/Shared/Components/{Nombre de componente de vista}/{Nombre de vista}/Views/Shared/Components/{View Component Name}/{View Name}

El nombre de vista predeterminado para un componente de vista es Default, lo que significa que el archivo de vista normalmente se denominará Default.cshtml.The default view name for a view component is Default, which means your view file will typically be named Default.cshtml. Puede especificar un nombre de vista diferente al crear el resultado del componente de vista o al llamar al método View.You can specify a different view name when creating the view component result or when calling the View method.

Se recomienda que asigne el nombre Default.cshtml al archivo de vista y use la ruta de acceso Views/Shared/Components/{Nombre de componente de vista}/{Nombre de vista}.We recommend you name the view file Default.cshtml and use the Views/Shared/Components/{View Component Name}/{View Name} path. El componente de vista PriorityList usado en este ejemplo usa Views/Shared/Components/PriorityList/Default.cshtml para la vista del componente de vista.The PriorityList view component used in this sample uses Views/Shared/Components/PriorityList/Default.cshtml for the view component view.

Invocar un componente de vistaInvoking a view component

Para usar el componente de vista, llame a lo siguiente dentro de una vista:To use the view component, call the following inside a view:

@await Component.InvokeAsync("Name of view component", {Anonymous Type Containing Parameters})

Los parámetros se pasarán al método InvokeAsync.The parameters will be passed to the InvokeAsync method. El componente de vista PriorityList desarrollado en el artículo se invoca desde el archivo de vista Views/Todo/Index.cshtml.The PriorityList view component developed in the article is invoked from the Views/Todo/Index.cshtml view file. En la tabla siguiente, se llama al método InvokeAsync con dos parámetros:In the following, the InvokeAsync method is called with two parameters:

@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })

Invocación de un componente de vista como un asistente de etiquetasInvoking a view component as a Tag Helper

Para ASP.NET Core 1.1 y versiones posteriores, puede invocar un componente de vista como un asistente de etiquetas:For ASP.NET Core 1.1 and higher, you can invoke a view component as a Tag Helper:

<vc:priority-list max-priority="2" is-done="false">
</vc:priority-list>

Los parámetros de clase y método con grafía Pascal para los asistentes de etiquetas se convierten a su grafía kebab en minúsculas.Pascal-cased class and method parameters for Tag Helpers are translated into their lower kebab case. El asistente de etiquetas que va a invocar un componente de vista usa el elemento <vc></vc>.The Tag Helper to invoke a view component uses the <vc></vc> element. El componente de vista se especifica de la manera siguiente:The view component is specified as follows:

<vc:[view-component-name]
  parameter1="parameter1 value"
  parameter2="parameter2 value">
</vc:[view-component-name]>

Para usar un componente de vista como un asistente de etiquetas, registre el ensamblado que contiene el componente de vista mediante la directiva @addTagHelper.To use a view component as a Tag Helper, register the assembly containing the view component using the @addTagHelper directive. Si el componente de vista está en un ensamblado denominado MyWebApp, agregue la directiva siguiente al archivo _ViewImports.cshtml:If your view component is in an assembly called MyWebApp, add the following directive to the _ViewImports.cshtml file:

@addTagHelper *, MyWebApp

Puede registrar un componente de vista como un asistente de etiquetas en cualquier archivo que haga referencia al componente de vista.You can register a view component as a Tag Helper to any file that references the view component. Vea Administración del ámbito de los asistentes de etiquetas para más información sobre cómo registrar asistentes de etiquetas.See Managing Tag Helper Scope for more information on how to register Tag Helpers.

El método InvokeAsync usado en este tutorial:The InvokeAsync method used in this tutorial:

@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })

En el marcado del asistente de etiquetas:In Tag Helper markup:

<vc:priority-list max-priority="2" is-done="false">
</vc:priority-list>

En el ejemplo anterior, el componente de vista PriorityList se convierte en priority-list.In the sample above, the PriorityList view component becomes priority-list. Los parámetros para el componente de vista se pasan como atributos en grafía kebab en minúsculas.The parameters to the view component are passed as attributes in lower kebab case.

Invocar un componente de vista directamente desde un controladorInvoking a view component directly from a controller

Los componentes de vista suelen invocarse desde una vista, pero se pueden invocar directamente desde un método de controlador.View components are typically invoked from a view, but you can invoke them directly from a controller method. Aunque los componentes de vista no definen puntos de conexión como controladores, se puede implementar fácilmente una acción del controlador que devuelva el contenido de ViewComponentResult.While view components don't define endpoints like controllers, you can easily implement a controller action that returns the content of a ViewComponentResult.

En este ejemplo, se llama al componente de vista directamente desde el controlador:In this example, the view component is called directly from the controller:

public IActionResult IndexVC()
{
    return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}

Tutorial: Creación de un componente de vista simpleWalkthrough: Creating a simple view component

Descargue, compile y pruebe el código de inicio.Download, build and test the starter code. Se trata de un proyecto simple con un controlador Todo que muestra una lista de tareas pendientes.It's a simple project with a Todo controller that displays a list of Todo items.

Lista de tareas pendientes

Agregar una clase ViewComponentAdd a ViewComponent class

Cree una carpeta ViewComponents y agregue la siguiente clase PriorityListViewComponent:Create a ViewComponents folder and add the following PriorityListViewComponent class:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;

namespace ViewComponentSample.ViewComponents
{
    public class PriorityListViewComponent : ViewComponent
    {
        private readonly ToDoContext db;

        public PriorityListViewComponent(ToDoContext context)
        {
            db = context;
        }

        public async Task<IViewComponentResult> InvokeAsync(
        int maxPriority, bool isDone)
        {
            var items = await GetItemsAsync(maxPriority, isDone);
            return View(items);
        }
        private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
        {
            return db.ToDo.Where(x => x.IsDone == isDone &&
                                 x.Priority <= maxPriority).ToListAsync();
        }
    }
}

Notas sobre el código:Notes on the code:

  • Las clases de componentes de vista pueden estar contenidas en cualquier carpeta del proyecto.View component classes can be contained in any folder in the project.

  • Dado que el nombre de clase PriorityListViewComponent acaba con el sufijo ViewComponent, el tiempo de ejecución usará la cadena "PriorityList" cuando haga referencia al componente de clase desde una vista.Because the class name PriorityListViewComponent ends with the suffix ViewComponent, the runtime will use the string "PriorityList" when referencing the class component from a view. Más adelante explicaremos esta cuestión con más detalle.I'll explain that in more detail later.

  • El atributo [ViewComponent] puede cambiar el nombre usado para hacer referencia a un componente de vista.The [ViewComponent] attribute can change the name used to reference a view component. Por ejemplo, podríamos haber asignado a la clase el nombre XYZ y aplicado el atributo ViewComponent:For example, we could've named the class XYZ and applied the ViewComponent attribute:

    [ViewComponent(Name = "PriorityList")]
       public class XYZ : ViewComponent
    
  • El atributo [ViewComponent] anterior le indica al selector de componentes de vista que use el nombre PriorityList al buscar las vistas asociadas al componente y que use la cadena "PriorityList" al hacer referencia al componente de clase desde una vista.The [ViewComponent] attribute above tells the view component selector to use the name PriorityList when looking for the views associated with the component, and to use the string "PriorityList" when referencing the class component from a view. Más adelante explicaremos esta cuestión con más detalle.I'll explain that in more detail later.

  • El componente usa la inserción de dependencias para que el contexto de datos esté disponible.The component uses dependency injection to make the data context available.

  • InvokeAsync expone un método al que se puede llamar desde una vista y puede tomar un número arbitrario de argumentos.InvokeAsync exposes a method which can be called from a view, and it can take an arbitrary number of arguments.

  • El método InvokeAsync devuelve el conjunto de elementos ToDo que cumplen los parámetros isDone y maxPriority.The InvokeAsync method returns the set of ToDo items that satisfy the isDone and maxPriority parameters.

Crear la vista de Razor del componente de vistaCreate the view component Razor view

  • Cree la carpeta Views/Shared/Components.Create the Views/Shared/Components folder. Esta carpeta debe denominarse Components.This folder must be named Components.

  • Cree la carpeta Views/Shared/Components/PriorityList.Create the Views/Shared/Components/PriorityList folder. El nombre de esta carpeta debe coincidir con el nombre de la clase de componente de vista o con el nombre de la clase sin el sufijo (si se ha seguido la convención y se ha usado el sufijo ViewComponent en el nombre de clase).This folder name must match the name of the view component class, or the name of the class minus the suffix (if we followed convention and used the ViewComponent suffix in the class name). Si ha usado el atributo ViewComponent, el nombre de clase debe coincidir con la designación del atributo.If you used the ViewComponent attribute, the class name would need to match the attribute designation.

  • Cree una vista de Razor Views/Shared/Components/PriorityList/Default.cshtml: [!code-cshtml]Create a Views/Shared/Components/PriorityList/Default.cshtml Razor view: [!code-cshtml]

    La vista de Razor toma una lista de TodoItem y muestra estos elementos.The Razor view takes a list of TodoItem and displays them. Si el método InvokeAsync del componente de vista no pasa el nombre de la vista (como en nuestro ejemplo), se usa Default para el nombre de vista, según la convención.If the view component InvokeAsync method doesn't pass the name of the view (as in our sample), Default is used for the view name by convention. Más adelante en el tutorial veremos cómo pasar el nombre de la vista.Later in the tutorial, I'll show you how to pass the name of the view. Para reemplazar el estilo predeterminado de un controlador concreto, agregue una vista a la carpeta de vistas específicas del controlador (por ejemplo, Views/Todo/Components/PriorityList/Default.cshtml).To override the default styling for a specific controller, add a view to the controller-specific view folder (for example Views/Todo/Components/PriorityList/Default.cshtml).

    Si el componente de vista es específico del controlador, puede agregarlo a la carpeta específica del controlador (Views/Todo/Components/PriorityList/Default.cshtml).If the view component is controller-specific, you can add it to the controller-specific folder (Views/Todo/Components/PriorityList/Default.cshtml).

  • Agregue un elemento div que contenga una llamada al componente de lista de prioridad en la parte inferior del archivo Views/Todo/index.cshtml:Add a div containing a call to the priority list component to the bottom of the Views/Todo/index.cshtml file:

    </table>
    <div>
        @await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false })
    </div>
    

El marcado @await Component.InvokeAsync muestra la sintaxis para llamar a los componentes de vista.The markup @await Component.InvokeAsync shows the syntax for calling view components. El primer argumento es el nombre del componente que se quiere invocar o llamar.The first argument is the name of the component we want to invoke or call. Los parámetros siguientes se pasan al componente.Subsequent parameters are passed to the component. InvokeAsync puede tomar un número arbitrario de argumentos.InvokeAsync can take an arbitrary number of arguments.

Pruebe la aplicación.Test the app. En la imagen siguiente se muestra la lista de tareas pendientes y los elementos de prioridad:The following image shows the ToDo list and the priority items:

lista de tareas pendientes y elementos de prioridad

También puede llamar al componente de vista directamente desde el controlador:You can also call the view component directly from the controller:

public IActionResult IndexVC()
{
    return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}

elementos de prioridad de la acción IndexVC

Especificar un nombre de vistaSpecifying a view name

En algunos casos, puede ser necesario que un componente de vista complejo especifique una vista no predeterminada.A complex view component might need to specify a non-default view under some conditions. En el código siguiente se muestra cómo especificar la vista "PVC" desde el método InvokeAsync.The following code shows how to specify the "PVC" view from the InvokeAsync method. Actualice el método InvokeAsync en la clase PriorityListViewComponent.Update the InvokeAsync method in the PriorityListViewComponent class.

public async Task<IViewComponentResult> InvokeAsync(
    int maxPriority, bool isDone)
{
    string MyView = "Default";
    // If asking for all completed tasks, render with the "PVC" view.
    if (maxPriority > 3 && isDone == true)
    {
        MyView = "PVC";
    }
    var items = await GetItemsAsync(maxPriority, isDone);
    return View(MyView, items);
}

Copie el archivo Views/Shared/Components/PriorityList/Default.cshtml en una vista denominada Views/Shared/Components/PriorityList/PVC.cshtml.Copy the Views/Shared/Components/PriorityList/Default.cshtml file to a view named Views/Shared/Components/PriorityList/PVC.cshtml. Agregue un encabezado para indicar que se está usando la vista PVC.Add a heading to indicate the PVC view is being used.

@model IEnumerable<ViewComponentSample.Models.TodoItem>

<h2> PVC Named Priority Component View</h2>
<h4>@ViewBag.PriorityMessage</h4>
<ul>
    @foreach (var todo in Model)
    {
        <li>@todo.Name</li>
    }
</ul>

Actualice Views/TodoList/Index.cshtml:Update Views/TodoList/Index.cshtml:

@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })

Ejecute la aplicación y compruebe la vista PVC.Run the app and verify PVC view.

Componente de vista de prioridad

Si la vista PVC no se representa, compruebe que está llamando al componente de vista con prioridad cuatro o superior.If the PVC view isn't rendered, verify you are calling the view component with a priority of 4 or higher.

Examinar la ruta de acceso de la vistaExamine the view path

  • Cambie el parámetro de prioridad a tres o menos para que no se devuelva la vista de prioridad.Change the priority parameter to three or less so the priority view isn't returned.

  • Cambie temporalmente el nombre de Views/Todo/Components/PriorityList/Default.cshtml a 1Default.cshtml.Temporarily rename the Views/Todo/Components/PriorityList/Default.cshtml to 1Default.cshtml.

  • Pruebe la aplicación. Obtendrá el siguiente error:Test the app, you'll get the following error:

    An unhandled exception occurred while processing the request.
    InvalidOperationException: The view 'Components/PriorityList/Default' wasn't found. The following locations were searched:
    /Views/ToDo/Components/PriorityList/Default.cshtml
    /Views/Shared/Components/PriorityList/Default.cshtml
    EnsureSuccessful
    
  • Copie Views/Todo/Components/PriorityList/1Default.cshtml en Views/Shared/Components/PriorityList/Default.cshtml.Copy Views/Todo/Components/PriorityList/1Default.cshtml to Views/Shared/Components/PriorityList/Default.cshtml.

  • Agregue algún marcado a la vista de componentes de vista de la lista de tareas pendientes Shared para indicar que la vista está en la carpeta Shared.Add some markup to the Shared Todo view component view to indicate the view is from the Shared folder.

  • Pruebe la vista de componentes Shared.Test the Shared component view.

Salida de la lista de tareas pendientes con la vista de componentes Shared

Evitar cadenas mágicasAvoiding magic strings

Si busca seguridad en tiempo de compilación, puede reemplazar el nombre del componente de vista codificado de forma rígida por el nombre de clase.If you want compile time safety, you can replace the hard-coded view component name with the class name. Cree el componente de vista sin el sufijo "ViewComponent":Create the view component without the "ViewComponent" suffix:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ViewComponentSample.Models;

namespace ViewComponentSample.ViewComponents
{
    public class PriorityList : ViewComponent
    {
        private readonly ToDoContext db;

        public PriorityList(ToDoContext context)
        {
            db = context;
        }

        public async Task<IViewComponentResult> InvokeAsync(
        int maxPriority, bool isDone)
        {
            var items = await GetItemsAsync(maxPriority, isDone);
            return View(items);
        }
        private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
        {
            return db.ToDo.Where(x => x.IsDone == isDone &&
                                 x.Priority <= maxPriority).ToListAsync();
        }
    }
}

Agregue una instrucción using para su archivo de vista de Razor y use el operador nameof:Add a using statement to your Razor view file, and use the nameof operator:

@using ViewComponentSample.Models
@using ViewComponentSample.ViewComponents
@model IEnumerable<TodoItem>

<h2>ToDo nameof</h2>
<!-- Markup removed for brevity.  -->

<div>

    @await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })
</div>

Realizar el trabajo sincrónicoPerform synchronous work

El marco controla la invocación de un método Invoke sincrónico si no necesita realizar un trabajo asincrónico.The framework handles invoking a synchronous Invoke method if you don't need to perform asynchronous work. El método siguiente crea un componente de vista Invoke sincrónico:The following method creates a synchronous Invoke view component:

public class PriorityList : ViewComponent
{
    public IViewComponentResult Invoke(int maxPriority, bool isDone)
    {
        var items = new List<string> { $"maxPriority: {maxPriority}", $"isDone: {isDone}" };
        return View(items);
    }
}

El archivo de Razor del componente de vista enumera las cadenas pasadas al método Invoke (Views/Home/Components/PriorityList/Default.cshtml):The view component's Razor file lists the strings passed to the Invoke method (Views/Home/Components/PriorityList/Default.cshtml):

@model List<string>

<h3>Priority Items</h3>
<ul>
    @foreach (var item in Model)
    {
        <li>@item</li>
    }
</ul>

Se invoca el componente de vista en un archivo de Razor (por ejemplo, Views/Home/Index.cshtml) con uno de los siguientes métodos:The view component is invoked in a Razor file (for example, Views/Home/Index.cshtml) using one of the following approaches:

Para usar el método IViewComponentHelper, llame a Component.InvokeAsync:To use the IViewComponentHelper approach, call Component.InvokeAsync:

Se invoca el componente de vista en un archivo de Razor (por ejemplo, Views/Home/Index.cshtml) con IViewComponentHelper.The view component is invoked in a Razor file (for example, Views/Home/Index.cshtml) with IViewComponentHelper.

Llame a Component.InvokeAsync:Call Component.InvokeAsync:

@await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })

Para usar el asistente de etiquetas, registre el ensamblado que contiene el componente de vista con el uso de la directiva @addTagHelper (el componente de vista se encuentra en un ensamblado denominado MyWebApp):To use the Tag Helper, register the assembly containing the View Component using the @addTagHelper directive (the view component is in an assembly called MyWebApp):

@addTagHelper *, MyWebApp

Use el asistente de etiquetas del componente de vista en el archivo de marcado de Razor:Use the view component Tag Helper in the Razor markup file:

<vc:priority-list max-priority="999" is-done="false">
</vc:priority-list>

La firma del método de PriorityList.Invoke es sincrónica, pero Razor busca y llama al método con Component.InvokeAsync en el archivo de marcado.The method signature of PriorityList.Invoke is synchronous, but Razor finds and calls the method with Component.InvokeAsync in the markup file.

Recursos adicionalesAdditional resources