Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Por Rick Anderson
Ver componentes
Os componentes de visualização são semelhantes às vistas parciais, mas são muito mais poderosos. Os componentes de exibição não usam vinculação de modelo, eles dependem dos dados passados ao chamar o componente de exibição. Este artigo foi escrito usando controladores e modos de exibição, mas os componentes de exibição funcionam com Razor o Pages.
Um componente de visualização:
- Renderiza uma parte em vez de uma resposta inteira.
- Inclui os mesmos benefícios de separação de responsabilidades e capacidade de teste encontrados entre um controlador e uma visualização.
- Pode ter parâmetros e lógica de negócio.
- Normalmente é invocado a partir de uma página de layout.
Os componentes de exibição destinam-se a serem utilizados em qualquer lugar onde a lógica de renderização que possa ser reutilizada seja demasiado complexa para uma exibição parcial, como:
- Menus de navegação dinâmica
- Nuvem de tags, onde consulta o banco de dados
- Painel Iniciar sessão
- Carrinho de compras
- Artigos publicados recentemente
- Conteúdo da barra lateral em um blog
- Um painel de autenticação que seria renderizado em cada página e mostraria os links para terminar sessão ou iniciar sessão, dependendo do estado de autenticação do utilizador.
Um componente de exibição consiste em duas partes:
- A classe, normalmente derivada de ViewComponent
- O resultado que ele retorna, normalmente uma visualização.
Como os controladores, um componente de exibição pode ser um POCO, mas a maioria dos desenvolvedores aproveita os métodos e propriedades disponíveis derivando do ViewComponent.
Ao considerar se os componentes de exibição atendem às especificações de um aplicativo, considere usar componentes Razor em vez disso. Razor componentes também combinam marcação com código C# para produzir unidades de interface do usuário reutilizáveis. Razor componentes são projetados para aumentar a produtividade dos desenvolvedores ao oferecer lógica e composição da interface de utilizador no lado do cliente. Para obter mais informações, consulte componentes do ASP.NET Core Razor. Para obter informações sobre como incorporar Razor componentes em um aplicativo MVC ou Razor Pages, consulte Integrar componentes ASP.NET Core Razor com MVC ou Razor Pages.
Criar um componente de exibição
Esta seção contém os requisitos de alto nível para criar um componente de exibição. Mais adiante no artigo, examinaremos cada etapa em detalhes e criaremos um componente de exibição.
A classe do componente de exibição
Uma classe de componente de exibição pode ser criada por qualquer um dos seguintes:
- Derivando de ViewComponent
- Decorando uma classe com o
[ViewComponent]atributo ou derivando de uma classe com o[ViewComponent]atributo - Criando uma classe onde o nome termina com o sufixo
ViewComponent
Como os controladores, os componentes de visualização devem ser classes públicas, não aninhadas e não abstratas. O nome do componente de exibição é o nome da classe com o sufixo ViewComponent removido. Ele também pode ser explicitamente especificado usando a Name propriedade.
Uma classe de componente de exibição:
- Suporta injeção de dependência do construtor
- Não participa do ciclo de vida do controlador, portanto, os filtros não podem ser usados em um componente de exibição
Para evitar que uma classe que tenha um sufixo que não diferencia maiúsculas de minúsculas ViewComponent seja tratada como um componente de exibição, decore a classe com o [NonViewComponent] atributo:
using Microsoft.AspNetCore.Mvc;
[NonViewComponent]
public class ReviewComponent
{
public string Status(string name) => JobStatus.GetCurrentStatus(name);
}
Exibir métodos de componentes
Um componente de exibição define sua lógica em:
-
InvokeAsyncmétodo que retornaTask<IViewComponentResult>. -
Invokemétodo síncrono que retorna um IViewComponentResult.
Os parâmetros vêm diretamente da invocação do componente de exibição, não da vinculação do modelo. Um componente de exibição nunca lida diretamente com uma solicitação. Normalmente, uma vista inicializa um modelo e passa-o para outra vista chamando o método View. Em resumo, consulte os métodos do componente:
- Defina um
InvokeAsyncmétodo que retorna umTask<IViewComponentResult>ou um método síncronoInvokeque retorna umIViewComponentResult. - Normalmente, inicializa um modelo e o passa para um modo de exibição chamando o método ViewComponent.View .
- Os parâmetros vêm do método de chamada, não HTTP. Não há vinculação de modelo.
- Não são acessíveis diretamente como um endpoint HTTP. Eles geralmente são invocados em um modo de exibição. Um componente de exibição nunca lida com uma solicitação.
- Estão sobrecarregados na assinatura em vez de quaisquer detalhes da solicitação HTTP atual.
Ver caminho de pesquisa
O runtime procura a vista nos seguintes caminhos:
- /Views/{Nome do Controlador}/Componentes/{Nome do Componente de Vista}/{Nome da Vista}
- /views/shareed/components/{view component name}/{view name}
- /Pages/Shared/Components/{Nome do Componente de Visualização}/{Nome da Visualização}
- /areas/{Area Name}/views/shared/components/{view component name}/{view name}
O caminho de pesquisa aplica-se a projetos que usam controladores + visualizações e Razor Páginas.
O nome de exibição padrão para um componente de exibição é Default, o que significa que os arquivos de exibição normalmente serão nomeados Default.cshtml. Um nome de exibição diferente pode ser especificado ao criar o resultado do componente de exibição ou ao chamar o View método.
Recomendamos nomear o arquivo Default.cshtml de exibição e usar o caminho Views/Shared/Components/{View Component Name}/{View Name} . O componente de visualização PriorityList usado neste exemplo utiliza Views/Shared/Components/PriorityList/Default.cshtml para a renderização do componente de visualização.
Personalizar o caminho de pesquisa da exibição
Para personalizar o caminho de pesquisa da exibição, modifique a coleção Razor de ViewLocationFormats. Por exemplo, para pesquisar visões dentro do caminho /Components/{View Component Name}/{View Name}, adicione um novo item à coleção:
using Microsoft.EntityFrameworkCore;
using ViewComponentSample.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews()
.AddRazorOptions(options =>
{
options.ViewLocationFormats.Add("/{0}.cshtml");
});
builder.Services.AddDbContext<ToDoContext>(options =>
options.UseInMemoryDatabase("db"));
var app = builder.Build();
// Remaining code removed for brevity.
No código anterior, o espaço reservado {0} representa o caminho Components/{View Component Name}/{View Name}.
Invocar um componente de exibição
Para usar o componente de exibição, chame o seguinte dentro de uma visualização:
@await Component.InvokeAsync("Name of view component",
{Anonymous Type Containing Parameters})
Os parâmetros são passados para o InvokeAsync método. O componente de exibição PriorityList desenvolvido no artigo é invocado no arquivo de exibição Views/ToDo/Index.cshtml. No código a seguir, o InvokeAsync método é chamado com dois parâmetros:
</table>
<div>
Maximum Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync("PriorityList",
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
Invoque um componente de exibição como um Auxiliar de Tag
Um componente View pode ser invocado como um auxiliar de tag:
<div>
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@{
int maxPriority = Convert.ToInt32(ViewData["maxPriority"]);
bool isDone = Convert.ToBoolean(ViewData["isDone"]);
}
<vc:priority-list max-priority=maxPriority is-done=isDone>
</vc:priority-list>
</div>
Os parâmetros de classe e método em PascalCase para Tag Helpers são traduzidos para o seu caso de kebab. O Auxiliar de Tag para invocar um componente de exibição usa o <vc></vc> elemento . O componente de exibição é especificado da seguinte maneira:
<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>
Para usar um componente de visualização como um auxiliar de tag, registe o assembly que contém o componente de visualização usando a diretiva @addTagHelper. Se o componente de exibição estiver em um assembly chamado MyWebApp, adicione a seguinte diretiva ao _ViewImports.cshtml arquivo:
@addTagHelper *, MyWebApp
Um componente de visualização pode ser registado como um Tag Helper para qualquer ficheiro que faça referência ao componente de visualização. Consulte Gerenciando o escopo do auxiliar de tag para obter mais informações sobre como registrar auxiliares de tag.
O InvokeAsync método usado neste tutorial:
@await Component.InvokeAsync("PriorityList",
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
Na marcação anterior, o PriorityList componente de exibição torna-se priority-list. Os parâmetros para o componente de visualização são passados como atributos em kebab case.
Invoque um componente de exibição diretamente de um controlador
Os componentes de exibição normalmente são invocados a partir de uma vista, mas podem ser invocados diretamente de um método do controlador. Embora os componentes de visualização não definam pontos de extremidade como os controladores, uma ação do controlador que retorne o conteúdo de um ViewComponentResult pode ser implementada.
No exemplo a seguir, o componente de exibição é chamado diretamente do controlador:
public IActionResult IndexVC(int maxPriority = 2, bool isDone = false)
{
return ViewComponent("PriorityList",
new {
maxPriority = maxPriority,
isDone = isDone
});
}
Criar um componente de exibição básica
Baixe, construa e teste o código inicial. É um projeto básico com um ToDo controlador que exibe uma lista de itens ToDo .
Atualize o controlador para passar o status de prioridade e conclusão
Atualize o método Index para usar os parâmetros de prioridade e status de conclusão:
using Microsoft.AspNetCore.Mvc;
using ViewComponentSample.Models;
namespace ViewComponentSample.Controllers;
public class ToDoController : Controller
{
private readonly ToDoContext _ToDoContext;
public ToDoController(ToDoContext context)
{
_ToDoContext = context;
_ToDoContext.Database.EnsureCreated();
}
public IActionResult Index(int maxPriority = 2, bool isDone = false)
{
var model = _ToDoContext!.ToDo!.ToList();
ViewData["maxPriority"] = maxPriority;
ViewData["isDone"] = isDone;
return View(model);
}
Adicionar uma classe ViewComponent
Adicione uma classe ViewComponent a ViewComponents/PriorityListViewComponent.cs:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
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 o código:
As classes de componente de exibição podem estar contidas em qualquer pasta do projeto.
Como o nome da classe PriorityListViewComponent termina com o sufixo ViewComponent, o tempo de execução usa a cadeia de caracteres
PriorityListao fazer referência ao componente de classe de uma exibição.O
[ViewComponent]atributo pode alterar o nome usado para fazer referência a um componente de exibição. Por exemplo, a classe poderia ter sido nomeadaXYZcom o seguinte[ViewComponent]atributo:[ViewComponent(Name = "PriorityList")] public class XYZ : ViewComponentO
[ViewComponent]atributo no código anterior informa ao seletor de componente de exibição para usar:- O nome
PriorityListao procurar os modos de exibição associados ao componente - A cadeia de caracteres "PriorityList" ao fazer referência ao componente de classe a partir de uma exibição.
- O nome
O componente usa a injeção de dependência para disponibilizar o contexto de dados.
InvokeAsyncexpõe um método que pode ser chamado a partir de uma vista e pode aceitar um número arbitrário de argumentos.O
InvokeAsyncmétodo retorna o conjunto deToDoitens que satisfazem osisDoneparâmetros emaxPriority.
Criar o componente de vista Razor
Crie a pasta Views/Shared/Components . Esta pasta deve ser denominada Componentes.
Crie a pasta Views/Shared/Components/PriorityList. Esse nome de pasta deve corresponder ao nome da classe do componente de exibição ou ao nome da classe menos o sufixo. Se o
ViewComponentatributo for usado, o nome da classe precisará corresponder à designação do atributo.Crie uma
Views/Shared/Components/PriorityList/Default.cshtmlRazor vista:@model IEnumerable<ViewComponentSample.Models.TodoItem> <h3>Priority Items</h3> <ul> @foreach (var todo in Model) { <li>@todo.Name</li> } </ul>O Razor recebe uma lista de
TodoIteme as exibe. Se o método do componenteInvokeAsyncnão passar o nome da vista, Default será usado como o nome da vista por convenção. Para substituir o estilo padrão de um controlador específico, adicione uma vista à pasta de vistas específica do controlador (por exemplo Views/ToDo/Components/PriorityList/Default.cshtml).Se o componente de exibição for específico do controlador, ele poderá ser adicionado à pasta específica do controlador. Por exemplo,
Views/ToDo/Components/PriorityList/Default.cshtmlé específico do controlador.Adicione um
divque contenha uma chamada para o componente da lista de prioridades na parte inferior do arquivoViews/ToDo/index.cshtml.</table> <div> Maximum Priority: @ViewData["maxPriority"] <br /> Is Complete: @ViewData["isDone"] @await Component.InvokeAsync("PriorityList", new { maxPriority = ViewData["maxPriority"], isDone = ViewData["isDone"] } ) </div>
A marcação @await Component.InvokeAsync mostra a sintaxe para chamar componentes de exibição. O primeiro argumento é o nome do componente que queremos invocar ou chamar. Os parâmetros subsequentes são passados para o componente.
InvokeAsync pode aceitar um número arbitrário de argumentos.
Teste o aplicativo. A imagem a seguir mostra a lista de ToDo e os itens prioritários:
O componente de visualização pode ser chamado diretamente do controlador:
public IActionResult IndexVC(int maxPriority = 2, bool isDone = false)
{
return ViewComponent("PriorityList",
new {
maxPriority = maxPriority,
isDone = isDone
});
}
Especificar um nome de componente de exibição
Um componente de exibição complexo pode precisar especificar um modo de exibição não padrão em algumas condições. O código a seguir mostra como especificar a exibição "PVC" do método InvokeAsync. Atualize o método InvokeAsync na classe PriorityListViewComponent.
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 o Views/Shared/Components/PriorityList/Default.cshtml arquivo para um modo de exibição chamado Views/Shared/Components/PriorityList/PVC.cshtml. Adicione um título para indicar que a visualização PVC está a ser utilizada.
@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>
Execute o aplicativo e verifique a visualização PVC.
Se a visualização PVC não for renderizada, verifique se o componente de exibição com prioridade de 4 ou superior é chamado.
Examinar o caminho de exibição
Altere o parâmetro priority para três ou menos para que a exibição de prioridade não seja retornada.
Renomeie temporariamente o
Views/ToDo/Components/PriorityList/Default.cshtmlpara1Default.cshtml.Teste o aplicativo, ocorre o seguinte erro:
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.cshtmlCopie
Views/ToDo/Components/PriorityList/1Default.cshtmlparaViews/Shared/Components/PriorityList/Default.cshtml.Adicione alguma marcação ao componente de vista ToDo Partilhada para indicar que a vista é proveniente da pasta Partilhada.
Teste a vista Compartilhada do componente.
Evite cadeias de caracteres codificadas
Para segurança no tempo de compilação, substitua o nome do componente de exibição codificado pelo nome da classe. Atualize o arquivo PriorityListViewComponent.cs para não usar o sufixo "ViewComponent":
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
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();
}
}
O arquivo de visualização:
</table>
<div>
Testing nameof(PriorityList) <br />
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync(nameof(PriorityList),
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
Uma sobrecarga do método Component.InvokeAsync que aceita um tipo CLR utiliza o operador typeof.
</table>
<div>
Testing typeof(PriorityList) <br />
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync(typeof(PriorityList),
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
Executar trabalho síncrono
A estrutura lida com a invocação de um método síncrono Invoke se o trabalho assíncrono não for necessário. O método a seguir cria um componente de exibição síncrona Invoke :
using Microsoft.AspNetCore.Mvc;
using ViewComponentSample.Models;
namespace ViewComponentSample.ViewComponents
{
public class PriorityListSync : ViewComponent
{
private readonly ToDoContext db;
public PriorityListSync(ToDoContext context)
{
db = context;
}
public IViewComponentResult Invoke(int maxPriority, bool isDone)
{
var x = db!.ToDo!.Where(x => x.IsDone == isDone &&
x.Priority <= maxPriority).ToList();
return View(x);
}
}
}
O ficheiro do componente de visualização Razor:
<div>
Testing nameof(PriorityList) <br />
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync(nameof(PriorityListSync),
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
O componente de exibição é invocado em um Razor arquivo (por exemplo, Views/Home/Index.cshtml) usando uma das seguintes abordagens:
Para usar a IViewComponentHelper abordagem, ligue para Component.InvokeAsync:
@await Component.InvokeAsync(nameof(PriorityList),
new { maxPriority = 4, isDone = true })
Para usar o Auxiliar de tag, registre o assembly que contém o componente View usando a @addTagHelper diretiva (o componente view está em um assembly chamado MyWebApp):
@addTagHelper *, MyWebApp
Use o componente de vista Tag Helper no arquivo de marcação Razor.
<vc:priority-list max-priority="999" is-done="false">
</vc:priority-list>
A assinatura do método PriorityList.Invoke é síncrona, mas Razor localiza e chama o método com Component.InvokeAsync no ficheiro de marcação.
Recursos adicionais
Ver componentes
Os componentes de visualização são semelhantes às vistas parciais, mas são muito mais poderosos. Os componentes de exibição não usam vinculação de modelo, eles dependem dos dados passados ao chamar o componente de exibição. Este artigo foi escrito usando controladores e modos de exibição, mas os componentes de exibição funcionam com Razor o Pages.
Um componente de visualização:
- Renderiza uma parte em vez de uma resposta inteira.
- Inclui os mesmos benefícios de separação de responsabilidades e capacidade de teste encontrados entre um controlador e uma visualização.
- Pode ter parâmetros e lógica de negócio.
- Normalmente é invocado a partir de uma página de layout.
Os componentes de exibição destinam-se a serem utilizados em qualquer lugar onde a lógica de renderização que possa ser reutilizada seja demasiado complexa para uma exibição parcial, como:
- Menus de navegação dinâmica
- Nuvem de tags, onde consulta o banco de dados
- Painel Iniciar sessão
- Carrinho de compras
- Artigos publicados recentemente
- Conteúdo da barra lateral em um blog
- Um painel de autenticação que seria renderizado em cada página e mostraria os links para terminar sessão ou iniciar sessão, dependendo do estado de autenticação do utilizador.
Um componente de exibição consiste em duas partes:
- A classe, normalmente derivada de ViewComponent
- O resultado que ele retorna, normalmente uma visualização.
Como os controladores, um componente de exibição pode ser um POCO, mas a maioria dos desenvolvedores aproveita os métodos e propriedades disponíveis derivando do ViewComponent.
Ao considerar se os componentes de exibição atendem às especificações de um aplicativo, considere usar componentes Razor em vez disso. Razor componentes também combinam marcação com código C# para produzir unidades de interface do usuário reutilizáveis. Razor componentes são projetados para aumentar a produtividade dos desenvolvedores ao oferecer lógica e composição da interface de utilizador no lado do cliente. Para obter mais informações, consulte componentes do ASP.NET Core Razor. Para obter informações sobre como incorporar Razor componentes em um aplicativo MVC ou Razor Pages, consulte Integrar componentes ASP.NET Core Razor com MVC ou Razor Pages.
Criar um componente de exibição
Esta seção contém os requisitos de alto nível para criar um componente de exibição. Mais adiante no artigo, examinaremos cada etapa em detalhes e criaremos um componente de exibição.
A classe do componente de exibição
Uma classe de componente de exibição pode ser criada por qualquer um dos seguintes:
- Derivando de ViewComponent
- Decorando uma classe com o
[ViewComponent]atributo ou derivando de uma classe com o[ViewComponent]atributo - Criando uma classe onde o nome termina com o sufixo
ViewComponent
Como os controladores, os componentes de visualização devem ser classes públicas, não aninhadas e não abstratas. O nome do componente de exibição é o nome da classe com o sufixo ViewComponent removido. Ele também pode ser explicitamente especificado usando a Name propriedade.
Uma classe de componente de exibição:
- Suporta injeção de dependência do construtor
- Não participa do ciclo de vida do controlador, portanto, os filtros não podem ser usados em um componente de exibição
Para evitar que uma classe que tenha um sufixo que não diferencia maiúsculas de minúsculas ViewComponent seja tratada como um componente de exibição, decore a classe com o [NonViewComponent] atributo:
using Microsoft.AspNetCore.Mvc;
[NonViewComponent]
public class ReviewComponent
{
public string Status(string name) => JobStatus.GetCurrentStatus(name);
}
Exibir métodos de componentes
Um componente de exibição define sua lógica em:
-
InvokeAsyncmétodo que retornaTask<IViewComponentResult>. -
Invokemétodo síncrono que retorna um IViewComponentResult.
Os parâmetros vêm diretamente da invocação do componente de exibição, não da vinculação do modelo. Um componente de exibição nunca lida diretamente com uma solicitação. Normalmente, uma vista inicializa um modelo e passa-o para outra vista chamando o método View. Em resumo, consulte os métodos do componente:
- Defina um
InvokeAsyncmétodo que retorna umTask<IViewComponentResult>ou um método síncronoInvokeque retorna umIViewComponentResult. - Normalmente, inicializa um modelo e o passa para um modo de exibição chamando o método ViewComponent.View .
- Os parâmetros vêm do método de chamada, não HTTP. Não há vinculação de modelo.
- Não são acessíveis diretamente como um endpoint HTTP. Eles geralmente são invocados em um modo de exibição. Um componente de exibição nunca lida com uma solicitação.
- Estão sobrecarregados na assinatura em vez de quaisquer detalhes da solicitação HTTP atual.
Ver caminho de pesquisa
O runtime procura a vista nos seguintes caminhos:
- /Views/{Nome do Controlador}/Componentes/{Nome do Componente de Vista}/{Nome da Vista}
- /views/shareed/components/{view component name}/{view name}
- /Pages/Shared/Components/{Nome do Componente de Visualização}/{Nome da Visualização}
- /areas/{Area Name}/views/shared/components/{view component name}/{view name}
O caminho de pesquisa aplica-se a projetos que usam controladores + visualizações e Razor Páginas.
O nome de exibição padrão para um componente de exibição é Default, o que significa que os arquivos de exibição normalmente serão nomeados Default.cshtml. Um nome de exibição diferente pode ser especificado ao criar o resultado do componente de exibição ou ao chamar o View método.
Recomendamos nomear o arquivo Default.cshtml de exibição e usar o caminho Views/Shared/Components/{View Component Name}/{View Name} . O componente de visualização PriorityList usado neste exemplo utiliza Views/Shared/Components/PriorityList/Default.cshtml para a renderização do componente de visualização.
Personalizar o caminho de pesquisa da exibição
Para personalizar o caminho de pesquisa da exibição, modifique a coleção Razor de ViewLocationFormats. Por exemplo, para pesquisar visões dentro do caminho /Components/{View Component Name}/{View Name}, adicione um novo item à coleção:
using Microsoft.EntityFrameworkCore;
using ViewComponentSample.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews()
.AddRazorOptions(options =>
{
options.ViewLocationFormats.Add("/{0}.cshtml");
});
builder.Services.AddDbContext<ToDoContext>(options =>
options.UseInMemoryDatabase("db"));
var app = builder.Build();
// Remaining code removed for brevity.
No código anterior, o espaço reservado {0} representa o caminho Components/{View Component Name}/{View Name}.
Invocar um componente de exibição
Para usar o componente de exibição, chame o seguinte dentro de uma visualização:
@await Component.InvokeAsync("Name of view component",
{Anonymous Type Containing Parameters})
Os parâmetros são passados para o InvokeAsync método. O componente de exibição PriorityList desenvolvido no artigo é invocado no arquivo de exibição Views/ToDo/Index.cshtml. No código a seguir, o InvokeAsync método é chamado com dois parâmetros:
</table>
<div>
Maximum Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync("PriorityList",
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
Invoque um componente de exibição como um Auxiliar de Tag
Um componente View pode ser invocado como um auxiliar de tag:
<div>
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@{
int maxPriority = Convert.ToInt32(ViewData["maxPriority"]);
bool isDone = Convert.ToBoolean(ViewData["isDone"]);
}
<vc:priority-list max-priority=maxPriority is-done=isDone>
</vc:priority-list>
</div>
Os parâmetros de classe e método em PascalCase para Tag Helpers são traduzidos para o seu caso de kebab. O Auxiliar de Tag para invocar um componente de exibição usa o <vc></vc> elemento . O componente de exibição é especificado da seguinte maneira:
<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>
Para usar um componente de visualização como um auxiliar de tag, registe o assembly que contém o componente de visualização usando a diretiva @addTagHelper. Se o componente de exibição estiver em um assembly chamado MyWebApp, adicione a seguinte diretiva ao _ViewImports.cshtml arquivo:
@addTagHelper *, MyWebApp
Um componente de visualização pode ser registado como um Tag Helper para qualquer ficheiro que faça referência ao componente de visualização. Consulte Gerenciando o escopo do auxiliar de tag para obter mais informações sobre como registrar auxiliares de tag.
O InvokeAsync método usado neste tutorial:
@await Component.InvokeAsync("PriorityList",
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
Na marcação anterior, o PriorityList componente de exibição torna-se priority-list. Os parâmetros para o componente de visualização são passados como atributos em kebab case.
Invoque um componente de exibição diretamente de um controlador
Os componentes de exibição normalmente são invocados a partir de uma vista, mas podem ser invocados diretamente de um método do controlador. Embora os componentes de visualização não definam pontos de extremidade como os controladores, uma ação do controlador que retorne o conteúdo de um ViewComponentResult pode ser implementada.
No exemplo a seguir, o componente de exibição é chamado diretamente do controlador:
public IActionResult IndexVC(int maxPriority = 2, bool isDone = false)
{
return ViewComponent("PriorityList",
new {
maxPriority = maxPriority,
isDone = isDone
});
}
Criar um componente de exibição básica
Baixe, construa e teste o código inicial. É um projeto básico com um ToDo controlador que exibe uma lista de itens ToDo .
Atualize o controlador para passar o status de prioridade e conclusão
Atualize o método Index para usar os parâmetros de prioridade e status de conclusão:
using Microsoft.AspNetCore.Mvc;
using ViewComponentSample.Models;
namespace ViewComponentSample.Controllers;
public class ToDoController : Controller
{
private readonly ToDoContext _ToDoContext;
public ToDoController(ToDoContext context)
{
_ToDoContext = context;
_ToDoContext.Database.EnsureCreated();
}
public IActionResult Index(int maxPriority = 2, bool isDone = false)
{
var model = _ToDoContext!.ToDo!.ToList();
ViewData["maxPriority"] = maxPriority;
ViewData["isDone"] = isDone;
return View(model);
}
Adicionar uma classe ViewComponent
Adicione uma classe ViewComponent a ViewComponents/PriorityListViewComponent.cs:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
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 o código:
As classes de componente de exibição podem estar contidas em qualquer pasta do projeto.
Como o nome da classe PriorityListViewComponent termina com o sufixo ViewComponent, o tempo de execução usa a cadeia de caracteres
PriorityListao fazer referência ao componente de classe de uma exibição.O
[ViewComponent]atributo pode alterar o nome usado para fazer referência a um componente de exibição. Por exemplo, a classe poderia ter sido nomeadaXYZcom o seguinte[ViewComponent]atributo:[ViewComponent(Name = "PriorityList")] public class XYZ : ViewComponentO
[ViewComponent]atributo no código anterior informa ao seletor de componente de exibição para usar:- O nome
PriorityListao procurar os modos de exibição associados ao componente - A cadeia de caracteres "PriorityList" ao fazer referência ao componente de classe a partir de uma exibição.
- O nome
O componente usa a injeção de dependência para disponibilizar o contexto de dados.
InvokeAsyncexpõe um método que pode ser chamado a partir de uma vista e pode aceitar um número arbitrário de argumentos.O
InvokeAsyncmétodo retorna o conjunto deToDoitens que satisfazem osisDoneparâmetros emaxPriority.
Criar o componente de vista Razor
Crie a pasta Views/Shared/Components . Esta pasta deve ser denominada Componentes.
Crie a pasta Views/Shared/Components/PriorityList. Esse nome de pasta deve corresponder ao nome da classe do componente de exibição ou ao nome da classe menos o sufixo. Se o
ViewComponentatributo for usado, o nome da classe precisará corresponder à designação do atributo.Crie uma
Views/Shared/Components/PriorityList/Default.cshtmlRazor vista:@model IEnumerable<ViewComponentSample.Models.TodoItem> <h3>Priority Items</h3> <ul> @foreach (var todo in Model) { <li>@todo.Name</li> } </ul>O Razor recebe uma lista de
TodoIteme as exibe. Se o método do componenteInvokeAsyncnão passar o nome da vista, Default será usado como o nome da vista por convenção. Para substituir o estilo padrão de um controlador específico, adicione uma vista à pasta de vistas específica do controlador (por exemplo Views/ToDo/Components/PriorityList/Default.cshtml).Se o componente de exibição for específico do controlador, ele poderá ser adicionado à pasta específica do controlador. Por exemplo,
Views/ToDo/Components/PriorityList/Default.cshtmlé específico do controlador.Adicione um
divque contenha uma chamada para o componente da lista de prioridades na parte inferior do arquivoViews/ToDo/index.cshtml.</table> <div> Maximum Priority: @ViewData["maxPriority"] <br /> Is Complete: @ViewData["isDone"] @await Component.InvokeAsync("PriorityList", new { maxPriority = ViewData["maxPriority"], isDone = ViewData["isDone"] } ) </div>
A marcação @await Component.InvokeAsync mostra a sintaxe para chamar componentes de exibição. O primeiro argumento é o nome do componente que queremos invocar ou chamar. Os parâmetros subsequentes são passados para o componente.
InvokeAsync pode aceitar um número arbitrário de argumentos.
Teste o aplicativo. A imagem a seguir mostra a lista de ToDo e os itens prioritários:
O componente de visualização pode ser chamado diretamente do controlador:
public IActionResult IndexVC(int maxPriority = 2, bool isDone = false)
{
return ViewComponent("PriorityList",
new {
maxPriority = maxPriority,
isDone = isDone
});
}
Especificar um nome de componente de exibição
Um componente de exibição complexo pode precisar especificar um modo de exibição não padrão em algumas condições. O código a seguir mostra como especificar a exibição "PVC" do método InvokeAsync. Atualize o método InvokeAsync na classe PriorityListViewComponent.
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 o Views/Shared/Components/PriorityList/Default.cshtml arquivo para um modo de exibição chamado Views/Shared/Components/PriorityList/PVC.cshtml. Adicione um título para indicar que a visualização PVC está a ser utilizada.
@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>
Execute o aplicativo e verifique a visualização PVC.
Se a visualização PVC não for renderizada, verifique se o componente de exibição com prioridade de 4 ou superior é chamado.
Examinar o caminho de exibição
Altere o parâmetro priority para três ou menos para que a exibição de prioridade não seja retornada.
Renomeie temporariamente o
Views/ToDo/Components/PriorityList/Default.cshtmlpara1Default.cshtml.Teste o aplicativo, ocorre o seguinte erro:
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.cshtmlCopie
Views/ToDo/Components/PriorityList/1Default.cshtmlparaViews/Shared/Components/PriorityList/Default.cshtml.Adicione alguma marcação ao componente de vista ToDo Partilhada para indicar que a vista é proveniente da pasta Partilhada.
Teste a vista Compartilhada do componente.
Evite cadeias de caracteres codificadas
Para segurança no tempo de compilação, substitua o nome do componente de exibição codificado pelo nome da classe. Atualize o arquivo PriorityListViewComponent.cs para não usar o sufixo "ViewComponent":
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
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();
}
}
O arquivo de visualização:
</table>
<div>
Testing nameof(PriorityList) <br />
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync(nameof(PriorityList),
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
Uma sobrecarga do método Component.InvokeAsync que aceita um tipo CLR utiliza o operador typeof.
</table>
<div>
Testing typeof(PriorityList) <br />
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync(typeof(PriorityList),
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
Executar trabalho síncrono
A estrutura lida com a invocação de um método síncrono Invoke se o trabalho assíncrono não for necessário. O método a seguir cria um componente de exibição síncrona Invoke :
using Microsoft.AspNetCore.Mvc;
using ViewComponentSample.Models;
namespace ViewComponentSample.ViewComponents
{
public class PriorityListSync : ViewComponent
{
private readonly ToDoContext db;
public PriorityListSync(ToDoContext context)
{
db = context;
}
public IViewComponentResult Invoke(int maxPriority, bool isDone)
{
var x = db!.ToDo!.Where(x => x.IsDone == isDone &&
x.Priority <= maxPriority).ToList();
return View(x);
}
}
}
O ficheiro do componente de visualização Razor:
<div>
Testing nameof(PriorityList) <br />
Maxium Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync(nameof(PriorityListSync),
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
O componente de exibição é invocado em um Razor arquivo (por exemplo, Views/Home/Index.cshtml) usando uma das seguintes abordagens:
Para usar a IViewComponentHelper abordagem, ligue para Component.InvokeAsync:
@await Component.InvokeAsync(nameof(PriorityList),
new { maxPriority = 4, isDone = true })
Para usar o Auxiliar de tag, registre o assembly que contém o componente View usando a @addTagHelper diretiva (o componente view está em um assembly chamado MyWebApp):
@addTagHelper *, MyWebApp
Use o componente de vista Tag Helper no arquivo de marcação Razor.
<vc:priority-list max-priority="999" is-done="false">
</vc:priority-list>
A assinatura do método PriorityList.Invoke é síncrona, mas Razor localiza e chama o método com Component.InvokeAsync no ficheiro de marcação.
Recursos adicionais
Visualizar ou descarregar amostra de código (como descarregar)
Ver componentes
Os componentes de visualização são semelhantes às vistas parciais, mas são muito mais poderosos. Os componentes de exibição não usam vinculação de modelo e dependem apenas dos dados fornecidos ao chamá-la. Este artigo foi escrito usando controladores e modos de exibição, mas os componentes de exibição também funcionam com Razor o Pages.
Um componente de visualização:
- Renderiza uma parte em vez de uma resposta inteira.
- Inclui os mesmos benefícios de separação de responsabilidades e capacidade de teste encontrados entre um controlador e uma visualização.
- Pode ter parâmetros e lógica de negócio.
- Normalmente é invocado a partir de uma página de layout.
Os componentes de exibição destinam-se a qualquer lugar onde você tenha uma lógica de renderização reutilizável que seja muito complexa para uma exibição parcial, como:
- Menus de navegação dinâmica
- Nuvem de tags (onde consulta o banco de dados)
- Painel de login
- Carrinho de compras
- Artigos publicados recentemente
- Conteúdo da barra lateral em um blog típico
- Um painel de login que seria renderizado em cada página e mostraria os links para logout ou login, dependendo do estado de login do usuário
Um componente de exibição consiste em duas partes: a classe (normalmente derivada de ViewComponent) e o resultado que retorna (normalmente uma exibição). Como os controladores, um componente de exibição pode ser um POCO, mas a maioria dos desenvolvedores aproveita os métodos e propriedades disponíveis derivando de ViewComponent.
Ao considerar se os componentes de exibição atendem às especificações de um aplicativo, considere usar componentes Razor em vez disso. Razor componentes também combinam marcação com código C# para produzir unidades de interface do usuário reutilizáveis. Razor componentes são projetados para aumentar a produtividade dos desenvolvedores ao oferecer lógica e composição da interface de utilizador no lado do cliente. Para obter mais informações, consulte componentes do ASP.NET Core Razor. Para obter informações sobre como incorporar Razor componentes em um aplicativo MVC ou Razor Pages, consulte Integrar componentes ASP.NET Core Razor com MVC ou Razor Pages.
Criando um componente de exibição
Esta seção contém os requisitos de alto nível para criar um componente de exibição. Mais adiante no artigo, examinaremos cada etapa em detalhes e criaremos um componente de exibição.
A classe do componente de exibição
Uma classe de componente de exibição pode ser criada por qualquer um dos seguintes:
- Derivando de ViewComponent
- Decorando uma classe com o
[ViewComponent]atributo ou derivando de uma classe com o[ViewComponent]atributo - Criando uma classe onde o nome termina com o sufixo ViewComponent
Como os controladores, os componentes de visualização devem ser classes públicas, não aninhadas e não abstratas. O nome do componente de visualização é o nome da classe ao qual se removeu o sufixo "ViewComponent". Ele também pode ser explicitamente especificado usando a ViewComponentAttribute.Name propriedade.
Uma classe de componente de exibição:
- Suporta totalmente a injeção de dependência do construtor
- Não participa do ciclo de vida do controlador, o que significa que você não pode usar filtros em um componente de exibição
Para impedir que uma classe que tenha um sufixo ViewComponent que não diferencia maiúsculas de minúsculas seja tratada como um componente de exibição, decore a classe com o atributo [NonViewComponent] :
[NonViewComponent]
public class ReviewComponent
{
// ...
Exibir métodos de componentes
Um componente de exibição define sua lógica em um InvokeAsync método que retorna um Task<IViewComponentResult> ou em um método síncrono Invoke que retorna um IViewComponentResult. Os parâmetros vêm diretamente da invocação do componente de exibição, não da vinculação do modelo. Um componente de exibição nunca lida diretamente com uma solicitação. Normalmente, uma vista inicializa um modelo e passa-o para outra vista chamando o método View. Em resumo, consulte os métodos do componente:
- Defina um
InvokeAsyncmétodo que retorna umTask<IViewComponentResult>ou um método síncronoInvokeque retorna umIViewComponentResult. - Normalmente, inicializa um modelo e o passa para uma exibição chamando o
ViewComponentViewmétodo. - Os parâmetros vêm do método de chamada, não HTTP. Não há vinculação de modelo.
- Não são acessíveis diretamente como um endpoint HTTP. Eles são invocados a partir do seu código (geralmente em uma vista). Um componente de exibição nunca lida com uma solicitação.
- Estão sobrecarregados na assinatura em vez de quaisquer detalhes da solicitação HTTP atual.
Ver caminho de pesquisa
O runtime procura a vista nos seguintes caminhos:
- /Views/{Nome do Controlador}/Componentes/{Nome do Componente de Vista}/{Nome da Vista}
- /views/shareed/components/{view component name}/{view name}
- /Pages/Shared/Components/{Nome do Componente de Visualização}/{Nome da Visualização}
- /areas/{Area Name}/views/shared/components/{view component name}/{view name}
O caminho de pesquisa aplica-se a projetos que usam controladores + visualizações e Razor Páginas.
O nome de exibição padrão para um componente de exibição é Padrão, o que significa que seu arquivo de exibição normalmente será nomeado Default.cshtml. Você pode especificar um nome de exibição diferente ao criar o resultado do componente de exibição ou ao chamar o View método.
Recomendamos que você nomeie o arquivo Default.cshtml de exibição e use o caminho Views/Shared/Components/{View Component Name}/{View Name} . O componente de visualização PriorityList usado neste exemplo utiliza Views/Shared/Components/PriorityList/Default.cshtml para a renderização do componente de visualização.
Personalizar o caminho de pesquisa da exibição
Para personalizar o caminho de pesquisa da exibição, modifique a coleção Razor de ViewLocationFormats. Por exemplo, para pesquisar visualizações dentro do caminho "/Components/{View Component Name}/{View Name}", adicione um novo item à coleção:
services.AddMvc()
.AddRazorOptions(options =>
{
options.ViewLocationFormats.Add("/{0}.cshtml");
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
No código anterior, o espaço reservado "{0}" representa o caminho "Components/{View Component Name}/{View Name}".
Invocando um componente de exibição
Para usar o componente de exibição, chame o seguinte dentro de uma visualização:
@await Component.InvokeAsync("Name of view component", {Anonymous Type Containing Parameters})
Os parâmetros serão passados para o InvokeAsync método. O componente de exibição PriorityList desenvolvido no artigo é invocado no arquivo de exibição Views/ToDo/Index.cshtml. A seguir, o InvokeAsync método é chamado com dois parâmetros:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
Invocando um componente de exibição como um Auxiliar de Tag
Para ASP.NET Core 1.1 e superior, você pode invocar um componente de exibição como um Auxiliar de tag:
<vc:priority-list max-priority="2" is-done="false">
</vc:priority-list>
Os parâmetros de classe e método em PascalCase para Tag Helpers são traduzidos para o seu caso de kebab. O Auxiliar de Tag para invocar um componente de exibição usa o <vc></vc> elemento . O componente de exibição é especificado da seguinte maneira:
<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>
Para usar um componente de visualização como um auxiliar de tag, registe o assembly que contém o componente de visualização usando a diretiva @addTagHelper. Se o componente de exibição estiver em um assembly chamado MyWebApp, adicione a seguinte diretiva ao _ViewImports.cshtml arquivo:
@addTagHelper *, MyWebApp
Você pode registrar um componente de exibição como um Auxiliar de Tag para qualquer arquivo que faça referência ao componente de exibição. Consulte Gerenciando o escopo do auxiliar de tag para obter mais informações sobre como registrar auxiliares de tag.
O InvokeAsync método usado neste tutorial:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
Na marcação do Tag Helper:
<vc:priority-list max-priority="2" is-done="false">
</vc:priority-list>
No exemplo acima, o PriorityList componente de exibição torna-se priority-list. Os parâmetros para o componente de visualização são passados como atributos em kebab case.
Invocando um componente de exibição diretamente de um controlador
Os componentes de exibição normalmente são invocados a partir de uma vista, mas pode invocá-los diretamente de um método de controlador. Embora os componentes de exibição não definam pontos de extremidade como controladores, você pode implementar facilmente uma ação do controlador que retorna o conteúdo de um ViewComponentResult.
Neste exemplo, o componente de exibição é chamado diretamente do controlador:
public IActionResult IndexVC()
{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
Passo a passo: Criando um componente de exibição simples
Baixe, construa e teste o código inicial. É um projeto simples com um ToDo controlador que exibe uma lista de itens ToDo .
Adicionar uma classe ViewComponent
Crie uma pasta ViewComponents e adicione a seguinte PriorityListViewComponent classe:
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 o código:
As classes de componente de exibição podem estar contidas em qualquer pasta do projeto.
Como o nome da classe PriorityListViewComponent termina com o sufixo ViewComponent, o tempo de execução usa a cadeia de caracteres
PriorityListao fazer referência ao componente de classe de uma exibição.O
[ViewComponent]atributo pode alterar o nome usado para fazer referência a um componente de exibição. Por exemplo, a classe poderia ter sido nomeadaXYZcom oViewComponentatributo:[ViewComponent(Name = "PriorityList")] public class XYZ : ViewComponentO
[ViewComponent]atributo no código anterior informa ao seletor de componente de exibição para usar:- O nome
PriorityListao procurar os modos de exibição associados ao componente - A cadeia de caracteres "PriorityList" ao fazer referência ao componente de classe a partir de uma exibição.
- O nome
O componente usa a injeção de dependência para disponibilizar o contexto de dados.
InvokeAsyncexpõe um método que pode ser chamado a partir de uma exibição, e pode ter um número arbitrário de argumentos.O
InvokeAsyncmétodo retorna o conjunto deToDoitens que satisfazem osisDoneparâmetros emaxPriority.
Criar o componente de vista Razor
Crie a pasta Views/Shared/Components . Esta pasta deve ser nomeada
Components.Crie a pasta Views/Shared/Components/PriorityList. Esse nome de pasta deve corresponder ao nome da classe do componente de exibição ou ao nome da classe menos o sufixo (se seguirmos a convenção e usarmos o sufixo ViewComponent no nome da classe). Se você usou o
ViewComponentatributo, o nome da classe precisará corresponder à designação do atributo.Crie uma
Views/Shared/Components/PriorityList/Default.cshtmlRazor vista:@model IEnumerable<ViewComponentSample.Models.TodoItem> <h3>Priority Items</h3> <ul> @foreach (var todo in Model) { <li>@todo.Name</li> } </ul>O Razor recebe uma lista de
TodoIteme as exibe. Se o método do componenteInvokeAsyncnão passar o nome da vista (como no nosso exemplo), Padrão será usado para o nome da vista por convenção. Mais adiante no tutorial, mostrarei como passar o nome da exibição. Para substituir o estilo padrão de um controlador específico, adicione uma vista à pasta de vistas específica do controlador (por exemplo Views/ToDo/Components/PriorityList/Default.cshtml).Se o componente de exibição for específico do controlador, você poderá adicioná-lo à pasta específica do controlador (
Views/ToDo/Components/PriorityList/Default.cshtml).Adicione um
divque contenha uma chamada para o componente da lista de prioridades na parte inferior do arquivoViews/ToDo/index.cshtml.</table> <div> @await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false }) </div>
A marcação @await Component.InvokeAsync mostra a sintaxe para chamar componentes de exibição. O primeiro argumento é o nome do componente que queremos invocar ou chamar. Os parâmetros subsequentes são passados para o componente.
InvokeAsync pode aceitar um número arbitrário de argumentos.
Teste o aplicativo. A imagem a seguir mostra a lista de ToDo e os itens prioritários:
Você também pode chamar o componente de exibição diretamente do controlador:
public IActionResult IndexVC()
{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
Especificando um nome de modo de exibição
Um componente de exibição complexo pode precisar especificar um modo de exibição não padrão em algumas condições. O código a seguir mostra como especificar a exibição "PVC" do método InvokeAsync. Atualize o método InvokeAsync na classe PriorityListViewComponent.
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 o Views/Shared/Components/PriorityList/Default.cshtml arquivo para um modo de exibição chamado Views/Shared/Components/PriorityList/PVC.cshtml. Adicione um título para indicar que a visualização PVC está a ser utilizada.
@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>
Atualização Views/ToDo/Index.cshtml:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
Execute o aplicativo e verifique a visualização PVC.
Se a visualização PVC não estiver renderizada, verifique se você está chamando o componente de exibição com prioridade igual ou superior a 4.
Examinar o caminho de exibição
Altere o parâmetro priority para três ou menos para que a exibição de prioridade não seja retornada.
Renomeie temporariamente o
Views/ToDo/Components/PriorityList/Default.cshtmlpara1Default.cshtml.Teste o aplicativo, você receberá o seguinte erro:
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 EnsureSuccessfulCopie
Views/ToDo/Components/PriorityList/1Default.cshtmlparaViews/Shared/Components/PriorityList/Default.cshtml.Adicione alguma marcação ao componente de vista ToDo Partilhada para indicar que a vista é proveniente da pasta Partilhada.
Teste a vista Compartilhada do componente.
Evitando cadeias de caracteres codificadas
Se quiser segurança no tempo de compilação, você pode substituir o nome do componente de exibição codificado pelo nome da classe. Crie o componente de visualização sem o sufixo "ViewComponent".
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();
}
}
}
Adicione uma using instrução ao seu Razor arquivo de exibição e use o nameof operador:
@using ViewComponentSample.Models
@using ViewComponentSample.ViewComponents
@model IEnumerable<TodoItem>
<h2>ToDo nameof</h2>
<!-- Markup removed for brevity. -->
<div>
@*
Note:
To use the below line, you need to #define no_suffix in ViewComponents/PriorityList.cs or it won't compile.
By doing so it will cause a problem to index as there will be multiple viewcomponents
with the same name after the compiler removes the suffix "ViewComponent"
*@
@*@await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })*@
</div>
Você pode usar uma sobrecarga de Component.InvokeAsync método que usa um tipo CLR. Lembre-se de usar o typeof operador neste caso:
@using ViewComponentSample.Models
@using ViewComponentSample.ViewComponents
@model IEnumerable<TodoItem>
<h2>ToDo typeof</h2>
<!-- Markup removed for brevity. -->
<div>
@await Component.InvokeAsync(typeof(PriorityListViewComponent), new { maxPriority = 4, isDone = true })
</div>
Executar trabalho síncrono
A estrutura lida com a invocação de um método síncrono Invoke se você não precisar executar trabalho assíncrono. O método a seguir cria um componente de exibição síncrona Invoke :
public class PriorityList : ViewComponent
{
public IViewComponentResult Invoke(int maxPriority, bool isDone)
{
var items = new List<string> { $"maxPriority: {maxPriority}", $"isDone: {isDone}" };
return View(items);
}
}
O arquivo do Razor componente de exibição lista as cadeias de caracteres passadas para o Invoke método (Views/Home/Components/PriorityList/Default.cshtml):
@model List<string>
<h3>Priority Items</h3>
<ul>
@foreach (var item in Model)
{
<li>@item</li>
}
</ul>
O componente de exibição é invocado em um Razor arquivo (por exemplo, Views/Home/Index.cshtml) usando uma das seguintes abordagens:
Para usar a IViewComponentHelper abordagem, ligue para Component.InvokeAsync:
@await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })
Para usar o Auxiliar de tag, registre o assembly que contém o componente View usando a @addTagHelper diretiva (o componente view está em um assembly chamado MyWebApp):
@addTagHelper *, MyWebApp
Use o componente de vista Tag Helper no arquivo de marcação Razor.
<vc:priority-list max-priority="999" is-done="false">
</vc:priority-list>
A assinatura do método PriorityList.Invoke é síncrona, mas Razor localiza e chama o método com Component.InvokeAsync no ficheiro de marcação.
Todos os parâmetros do componente de visualização são necessários
Cada parâmetro em um componente de exibição é um atributo obrigatório. Veja o sobre este problema do GitHub. Se algum parâmetro for omitido:
- A
InvokeAsyncassinatura do método não corresponderá, portanto, o método não será executado. - O ViewComponent não renderizará nenhuma marcação.
- Nenhum erro será gerado.