Wyświetlanie składników w programie ASP.NET Core
Autor: Rick Anderson
Składniki widoku
Składniki widoku są podobne do widoków częściowych, ale są znacznie bardziej zaawansowane. Składniki widoku nie korzystają z powiązania modelu. Zależą one od danych przekazywanych podczas wywoływania składnika widoku. Ten artykuł został napisany przy użyciu kontrolerów i widoków, ale składniki widoku współpracują ze stronamiRazor.
Składnik widoku:
- Renderuje fragment, a nie całą odpowiedź.
- Obejmuje te same kwestie związane z separacją i korzyściami z testowania znalezionymi między kontrolerem a widokiem.
- Może mieć parametry i logikę biznesową.
- Jest zwykle wywoływany ze strony układu.
Składniki widoku są przeznaczone w dowolnym miejscu, gdzie logika renderowania wielokrotnego użytku jest zbyt złożona dla widoku częściowego, takiego jak:
- Menu nawigacji dynamicznej
- Tagowanie chmury, w której wysyła zapytania do bazy danych
- Panel logowania
- Koszyk
- Ostatnio opublikowane artykuły
- Zawartość paska bocznego w blogu
- Panel logowania, który będzie renderowany na każdej stronie i wyświetla linki do wylogowania lub logowania, w zależności od stanu logowania użytkownika
Składnik widoku składa się z dwóch części:
- Klasa, zazwyczaj pochodzi z ViewComponent
- Wynik, który zwraca, zazwyczaj jest to widok.
Podobnie jak kontrolery, składnik widoku może być poco, ale większość deweloperów korzysta z metod i właściwości dostępnych przez wyprowadzanie z ViewComponentklasy .
Podczas rozważania, czy wyświetlanie składników spełnia specyfikacje aplikacji, rozważ użycie Razor składników. Razor składniki łączą również znaczniki z kodem C#, aby tworzyć jednostki interfejsu użytkownika wielokrotnego użytku. Razor składniki są zaprojektowane pod kątem produktywności deweloperów podczas zapewniania logiki i kompozycji interfejsu użytkownika po stronie klienta. Aby uzyskać więcej informacji, zobacz ASP.NET Podstawowe Razor składniki. Aby uzyskać informacje na temat dołączania Razor składników do aplikacji MVC lub Razor Pages, zobacz Integrowanie składników ASP.NET Core Razor z mvC lub Razor pages.
Tworzenie składnika widoku
Ta sekcja zawiera ogólne wymagania dotyczące tworzenia składnika widoku. W dalszej części artykułu szczegółowo sprawdzimy każdy krok i utworzymy składnik widoku.
Klasa składników widoku
Klasę składników widoku można utworzyć za pomocą dowolnego z następujących elementów:
- Wyprowadzanie z ViewComponent
- Dekorowanie klasy za pomocą atrybutu
[ViewComponent]
lub wyprowadzanie z klasy z atrybutem[ViewComponent]
- Tworzenie klasy, w której nazwa kończy się sufiksem
ViewComponent
Podobnie jak kontrolery, składniki widoku muszą być publiczne, niezagnieżdżone i nie abstrakcyjne klasy. Nazwa składnika widoku to nazwa klasy z usuniętym sufiksem ViewComponent
. Można go również jawnie określić przy użyciu Name właściwości .
Klasa składników widoku:
- Obsługuje wstrzykiwanie zależności konstruktora
- Nie bierze udziału w cyklu życia kontrolera, dlatego filtry nie mogą być używane w składniku widoku
Aby zapobiec traktowaniu klasy, która ma sufiks bez uwzględniania ViewComponent
wielkości liter, jest traktowana jako składnik widoku, udekoruj klasę za pomocą atrybutu [NonViewComponent]
:
using Microsoft.AspNetCore.Mvc;
[NonViewComponent]
public class ReviewComponent
{
public string Status(string name) => JobStatus.GetCurrentStatus(name);
}
Wyświetlanie metod składników
Składnik widoku definiuje jego logikę w elemencie :
InvokeAsync
metoda zwracającaTask<IViewComponentResult>
wartość .Invoke
metoda synchroniczna zwracająca element IViewComponentResult.
Parametry pochodzą bezpośrednio z wywołania składnika widoku, a nie z powiązania modelu. Składnik widoku nigdy nie obsługuje bezpośrednio żądania. Zazwyczaj składnik widoku inicjuje model i przekazuje go do widoku, wywołując metodę View
. Podsumowując, wyświetl metody składników:
- Zdefiniuj metodę
InvokeAsync
zwracającą metodęTask<IViewComponentResult>
synchronicznąInvoke
lub zwracającąIViewComponentResult
wartość . - Zazwyczaj inicjuje model i przekazuje go do widoku, wywołując metodę ViewComponent.View .
- Parametry pochodzą z metody wywołującej, a nie z protokołu HTTP. Nie ma powiązania modelu.
- Nie są dostępne bezpośrednio jako punkt końcowy HTTP. Są one zwykle wywoływane w widoku. Składnik widoku nigdy nie obsługuje żądania.
- Są przeciążone podpisem, a nie wszelkimi szczegółami z bieżącego żądania HTTP.
Wyświetlanie ścieżki wyszukiwania
Środowisko uruchomieniowe wyszukuje widok w następujących ścieżkach:
- /Views/{Nazwa kontrolera}/Składniki/{Wyświetl nazwę składnika}/{Nazwa widoku}
- /Views/Shared/Components/{Wyświetl nazwę składnika}/{Nazwa widoku}
- /Pages/Shared/Components/{Wyświetl nazwę składnika}/{Nazwa widoku}
- /Areas/{Nazwa obszaru}/Widoki/Udostępnione/Składniki/{Wyświetl nazwę składnika}/{Nazwa widoku}
Ścieżka wyszukiwania dotyczy projektów przy użyciu kontrolerów i widoków i Razor stron.
Domyślna nazwa widoku składnika widoku to Default
, co oznacza, że pliki widoku będą zwykle mieć nazwę Default.cshtml
. Podczas tworzenia wyniku składnika widoku lub wywoływania View
metody można określić inną nazwę widoku.
Zalecamy nazewnictwo pliku Default.cshtml
widoku i użycie ścieżki Views/Shared/Components/{Wyświetl nazwę składnika}/{Nazwa widoku} . Składnik PriorityList
widoku używany w tym przykładzie jest używany Views/Shared/Components/PriorityList/Default.cshtml
dla widoku składnika widoku.
Dostosowywanie ścieżki wyszukiwania widoku
Aby dostosować ścieżkę wyszukiwania widoku, zmodyfikuj RazorViewLocationFormats kolekcję . Aby na przykład wyszukać widoki w ścieżce /Components/{View Component Name}/{View Name}
, dodaj nowy element do kolekcji:
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.
W poprzednim kodzie symbol zastępczy {0}
reprezentuje ścieżkę Components/{View Component Name}/{View Name}
.
Wywoływanie składnika widoku
Aby użyć składnika widoku, wywołaj następujące elementy w widoku:
@await Component.InvokeAsync("Name of view component",
{Anonymous Type Containing Parameters})
Parametry są przekazywane do InvokeAsync
metody . Składnik PriorityList
widoku opracowany w artykule jest wywoływany z Views/ToDo/Index.cshtml
pliku widoku. W poniższym kodzie metoda jest wywoływana InvokeAsync
z dwoma parametrami:
</table>
<div>
Maximum Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync("PriorityList",
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
Wywoływanie składnika widoku jako pomocnika tagów
Składnik widoku można wywołać jako pomocnik tagów:
<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>
Parametry klasy i metody Pascal cased dla pomocników tagów są tłumaczone na ich przypadek kebab. Pomocnik tagów do wywoływania składnika widoku używa <vc></vc>
elementu . Składnik widoku jest określony w następujący sposób:
<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>
Aby użyć składnika widoku jako pomocnika tagów, zarejestruj zestaw zawierający składnik widoku przy użyciu @addTagHelper
dyrektywy . Jeśli składnik widoku znajduje się w zestawie o nazwie MyWebApp
, dodaj następującą dyrektywę _ViewImports.cshtml
do pliku:
@addTagHelper *, MyWebApp
Składnik widoku można zarejestrować jako pomocnik tagów do dowolnego pliku, który odwołuje się do składnika widoku. Aby uzyskać więcej informacji na temat rejestrowania pomocników tagów, zobacz Zarządzanie zakresem pomocnika tagów.
Metoda InvokeAsync
używana w tym samouczku:
@await Component.InvokeAsync("PriorityList",
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
W poprzednim znaczniku PriorityList
składnik widoku staje się .priority-list
Parametry składnika widoku są przekazywane jako atrybuty w przypadku kebab.
Wywoływanie składnika widoku bezpośrednio z kontrolera
Składniki widoku są zwykle wywoływane z widoku, ale mogą być wywoływane bezpośrednio z metody kontrolera. Chociaż składniki widoku nie definiują punktów końcowych, takich jak kontrolery, można zaimplementować akcję kontrolera zwracającą zawartość obiektu ViewComponentResult
.
W poniższym przykładzie składnik widoku jest wywoływany bezpośrednio z kontrolera:
public IActionResult IndexVC(int maxPriority = 2, bool isDone = false)
{
return ViewComponent("PriorityList",
new {
maxPriority = maxPriority,
isDone = isDone
});
}
Tworzenie podstawowego składnika widoku
Pobierz, skompiluj i przetestuj kod początkowy. Jest to podstawowy projekt z kontrolerem ToDo
, który wyświetla listę elementów zadań do wykonania .
Aktualizowanie kontrolera w celu przekazania priorytetu i stanu ukończenia
Zaktualizuj metodę tak Index
, aby korzystała z parametrów stanu priorytetu i ukończenia:
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);
}
Dodawanie klasy ViewComponent
Dodaj klasę ViewComponent do elementu 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();
}
}
Uwagi dotyczące kodu:
Klasy składników widoku mogą być zawarte w dowolnym folderze w projekcie.
Ponieważ nazwa klasy PriorityListViewComponent kończy się sufiksem ViewComponent, środowisko uruchomieniowe używa ciągu
PriorityList
podczas odwoływania się do składnika klasy z widoku.Atrybut
[ViewComponent]
może zmienić nazwę używaną do odwołowania się do składnika widoku. Na przykład klasa mogła mieć nazwęXYZ
z następującym[ViewComponent]
atrybutem:[ViewComponent(Name = "PriorityList")] public class XYZ : ViewComponent
Atrybut
[ViewComponent]
w poprzednim kodzie informuje selektora składników widoku do użycia:- Nazwa
PriorityList
podczas wyszukiwania widoków skojarzonych z składnikiem - Ciąg "PriorityList" podczas odwoływania się do składnika klasy z widoku.
- Nazwa
Składnik używa iniekcji zależności, aby udostępnić kontekst danych.
InvokeAsync
Uwidacznia metodę, którą można wywołać z widoku, i może przyjmować dowolną liczbę argumentów.Metoda
InvokeAsync
zwraca zestawToDo
elementów spełniającychisDone
parametry imaxPriority
.
Tworzenie widoku składnika Razor
Utwórz folder Views/Shared/Components. Ten folder musi mieć nazwę Components.
Utwórz folder Views/Shared/Components/PriorityList. Ta nazwa folderu musi być zgodna z nazwą klasy składnika widoku lub nazwą klasy minus sufiks.
ViewComponent
Jeśli atrybut jest używany, nazwa klasy musi być zgodna z oznaczeniem atrybutu.Views/Shared/Components/PriorityList/Default.cshtml
Razor Utwórz widok:@model IEnumerable<ViewComponentSample.Models.TodoItem> <h3>Priority Items</h3> <ul> @foreach (var todo in Model) { <li>@todo.Name</li> } </ul>
Widok Razor przyjmuje listę
TodoItem
i wyświetla je. Jeśli metoda składnikaInvokeAsync
widoku nie przekazuje nazwy widoku, wartość Domyślna jest używana dla nazwy widoku zgodnie z konwencją. Aby zastąpić domyślny styl określonego kontrolera, dodaj widok do folderu widoku specyficznego dla kontrolera (na przykład Views/ToDo/Components/PriorityList/Default.cshtml)..Jeśli składnik widoku jest specyficzny dla kontrolera, można go dodać do folderu specyficznego dla kontrolera. Na przykład
Views/ToDo/Components/PriorityList/Default.cshtml
jest specyficzny dla kontrolera.div
Dodaj element zawierający wywołanie składnika listy priorytetów w dolnej częściViews/ToDo/index.cshtml
pliku:</table> <div> Maximum Priority: @ViewData["maxPriority"] <br /> Is Complete: @ViewData["isDone"] @await Component.InvokeAsync("PriorityList", new { maxPriority = ViewData["maxPriority"], isDone = ViewData["isDone"] } ) </div>
Znacznik @await Component.InvokeAsync
pokazuje składnię wywoływania składników widoku. Pierwszym argumentem jest nazwa składnika, który chcemy wywołać lub wywołać. Kolejne parametry są przekazywane do składnika. InvokeAsync
może przyjmować dowolną liczbę argumentów.
Testowanie aplikacji. Na poniższej ilustracji przedstawiono listę Zadań do wykonania i elementy priorytetu:
Składnik widoku można wywołać bezpośrednio z kontrolera:
public IActionResult IndexVC(int maxPriority = 2, bool isDone = false)
{
return ViewComponent("PriorityList",
new {
maxPriority = maxPriority,
isDone = isDone
});
}
Określanie nazwy składnika widoku
Składnik widoku złożonego może wymagać określenia widoku innego niż domyślny w niektórych warunkach. Poniższy kod pokazuje, jak określić widok "PVC" z InvokeAsync
metody . Zaktualizuj metodę InvokeAsync
PriorityListViewComponent
w klasie .
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);
}
Views/Shared/Components/PriorityList/Default.cshtml
Skopiuj plik do widoku o nazwie Views/Shared/Components/PriorityList/PVC.cshtml
. Dodaj nagłówek, aby wskazać, że widok PVC jest używany.
@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>
Uruchom aplikację i sprawdź widok PVC.
Jeśli widok PVC nie jest renderowany, sprawdź, czy składnik widoku o priorytecie 4 lub wyższym jest wywoływany.
Badanie ścieżki widoku
Zmień parametr priorytetu na trzy lub mniej, aby widok priorytetu nie został zwrócony.
Tymczasowo zmień nazwę elementu na
Views/ToDo/Components/PriorityList/Default.cshtml
1Default.cshtml
.Przetestuj aplikację, wystąpi następujący błąd:
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
Skopiuj folder
Views/ToDo/Components/PriorityList/1Default.cshtml
do folderuViews/Shared/Components/PriorityList/Default.cshtml
.Dodaj znaczniki do widoku składników udostępnionego widoku zadań do wykonania, aby wskazać, że widok pochodzi z folderu Udostępnione.
Przetestuj widok składników udostępnionych .
Unikaj zakodowanych ciągów
W przypadku bezpieczeństwa czasu kompilacji zastąp nazwę składnika widoku zakodowanego na podstawie kodu nazwą klasy. Zaktualizuj plik PriorityListViewComponent.cs, aby nie używał sufiksu "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();
}
}
Plik widoku :
</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>
Przeciążenie Component.InvokeAsync
metody, która przyjmuje typ CLR, używa typeof
operatora :
</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>
Wykonywanie pracy synchronicznej
Platforma obsługuje wywoływanie metody synchronicznej, jeśli praca asynchroniczna Invoke
nie jest wymagana. Poniższa metoda tworzy synchroniczny Invoke
składnik widoku:
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);
}
}
}
Plik składnika Razor widoku:
<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>
Składnik widoku jest wywoływany w Razor pliku (na przykład Views/Home/Index.cshtml
) przy użyciu jednego z następujących metod:
Aby użyć podejścia, wywołaj metodę IViewComponentHelper Component.InvokeAsync
:
@await Component.InvokeAsync(nameof(PriorityList),
new { maxPriority = 4, isDone = true })
Aby użyć pomocnika tagów, zarejestruj zestaw zawierający składnik widoku przy użyciu @addTagHelper
dyrektywy (składnik widoku znajduje się w zestawie o nazwie MyWebApp
):
@addTagHelper *, MyWebApp
Użyj pomocnika tagu składnika widoku w Razor pliku znaczników:
<vc:priority-list max-priority="999" is-done="false">
</vc:priority-list>
Sygnatura PriorityList.Invoke
metody metody jest synchroniczna, ale Razor znajduje i wywołuje metodę w Component.InvokeAsync
pliku znaczników.
Dodatkowe zasoby
Składniki widoku
Składniki widoku są podobne do widoków częściowych, ale są znacznie bardziej zaawansowane. Składniki widoku nie korzystają z powiązania modelu. Zależą one od danych przekazywanych podczas wywoływania składnika widoku. Ten artykuł został napisany przy użyciu kontrolerów i widoków, ale składniki widoku współpracują ze stronamiRazor.
Składnik widoku:
- Renderuje fragment, a nie całą odpowiedź.
- Obejmuje te same kwestie związane z separacją i korzyściami z testowania znalezionymi między kontrolerem a widokiem.
- Może mieć parametry i logikę biznesową.
- Jest zwykle wywoływany ze strony układu.
Składniki widoku są przeznaczone w dowolnym miejscu, gdzie logika renderowania wielokrotnego użytku jest zbyt złożona dla widoku częściowego, takiego jak:
- Menu nawigacji dynamicznej
- Tagowanie chmury, w której wysyła zapytania do bazy danych
- Panel logowania
- Koszyk
- Ostatnio opublikowane artykuły
- Zawartość paska bocznego w blogu
- Panel logowania, który będzie renderowany na każdej stronie i wyświetla linki do wylogowania lub logowania, w zależności od stanu logowania użytkownika
Składnik widoku składa się z dwóch części:
- Klasa, zazwyczaj pochodzi z ViewComponent
- Wynik, który zwraca, zazwyczaj jest to widok.
Podobnie jak kontrolery, składnik widoku może być poco, ale większość deweloperów korzysta z metod i właściwości dostępnych przez wyprowadzanie z ViewComponentklasy .
Podczas rozważania, czy wyświetlanie składników spełnia specyfikacje aplikacji, rozważ użycie Razor składników. Razor składniki łączą również znaczniki z kodem C#, aby tworzyć jednostki interfejsu użytkownika wielokrotnego użytku. Razor składniki są zaprojektowane pod kątem produktywności deweloperów podczas zapewniania logiki i kompozycji interfejsu użytkownika po stronie klienta. Aby uzyskać więcej informacji, zobacz ASP.NET Podstawowe Razor składniki. Aby uzyskać informacje na temat dołączania Razor składników do aplikacji MVC lub Razor Pages, zobacz Integrowanie składników ASP.NET Core Razor z mvC lub Razor pages.
Tworzenie składnika widoku
Ta sekcja zawiera ogólne wymagania dotyczące tworzenia składnika widoku. W dalszej części artykułu szczegółowo sprawdzimy każdy krok i utworzymy składnik widoku.
Klasa składników widoku
Klasę składników widoku można utworzyć za pomocą dowolnego z następujących elementów:
- Wyprowadzanie z ViewComponent
- Dekorowanie klasy za pomocą atrybutu
[ViewComponent]
lub wyprowadzanie z klasy z atrybutem[ViewComponent]
- Tworzenie klasy, w której nazwa kończy się sufiksem
ViewComponent
Podobnie jak kontrolery, składniki widoku muszą być publiczne, niezagnieżdżone i nie abstrakcyjne klasy. Nazwa składnika widoku to nazwa klasy z usuniętym sufiksem ViewComponent
. Można go również jawnie określić przy użyciu Name właściwości .
Klasa składników widoku:
- Obsługuje wstrzykiwanie zależności konstruktora
- Nie bierze udziału w cyklu życia kontrolera, dlatego filtry nie mogą być używane w składniku widoku
Aby zapobiec traktowaniu klasy, która ma sufiks bez uwzględniania ViewComponent
wielkości liter, jest traktowana jako składnik widoku, udekoruj klasę za pomocą atrybutu [NonViewComponent]
:
using Microsoft.AspNetCore.Mvc;
[NonViewComponent]
public class ReviewComponent
{
public string Status(string name) => JobStatus.GetCurrentStatus(name);
}
Wyświetlanie metod składników
Składnik widoku definiuje jego logikę w elemencie :
InvokeAsync
metoda zwracającaTask<IViewComponentResult>
wartość .Invoke
metoda synchroniczna zwracająca element IViewComponentResult.
Parametry pochodzą bezpośrednio z wywołania składnika widoku, a nie z powiązania modelu. Składnik widoku nigdy nie obsługuje bezpośrednio żądania. Zazwyczaj składnik widoku inicjuje model i przekazuje go do widoku, wywołując metodę View
. Podsumowując, wyświetl metody składników:
- Zdefiniuj metodę
InvokeAsync
zwracającą metodęTask<IViewComponentResult>
synchronicznąInvoke
lub zwracającąIViewComponentResult
wartość . - Zazwyczaj inicjuje model i przekazuje go do widoku, wywołując metodę ViewComponent.View .
- Parametry pochodzą z metody wywołującej, a nie z protokołu HTTP. Nie ma powiązania modelu.
- Nie są dostępne bezpośrednio jako punkt końcowy HTTP. Są one zwykle wywoływane w widoku. Składnik widoku nigdy nie obsługuje żądania.
- Są przeciążone podpisem, a nie wszelkimi szczegółami z bieżącego żądania HTTP.
Wyświetlanie ścieżki wyszukiwania
Środowisko uruchomieniowe wyszukuje widok w następujących ścieżkach:
- /Views/{Nazwa kontrolera}/Składniki/{Wyświetl nazwę składnika}/{Nazwa widoku}
- /Views/Shared/Components/{Wyświetl nazwę składnika}/{Nazwa widoku}
- /Pages/Shared/Components/{Wyświetl nazwę składnika}/{Nazwa widoku}
- /Areas/{Nazwa obszaru}/Widoki/Udostępnione/Składniki/{Wyświetl nazwę składnika}/{Nazwa widoku}
Ścieżka wyszukiwania dotyczy projektów przy użyciu kontrolerów i widoków i Razor stron.
Domyślna nazwa widoku składnika widoku to Default
, co oznacza, że pliki widoku będą zwykle mieć nazwę Default.cshtml
. Podczas tworzenia wyniku składnika widoku lub wywoływania View
metody można określić inną nazwę widoku.
Zalecamy nazewnictwo pliku Default.cshtml
widoku i użycie ścieżki Views/Shared/Components/{Wyświetl nazwę składnika}/{Nazwa widoku} . Składnik PriorityList
widoku używany w tym przykładzie jest używany Views/Shared/Components/PriorityList/Default.cshtml
dla widoku składnika widoku.
Dostosowywanie ścieżki wyszukiwania widoku
Aby dostosować ścieżkę wyszukiwania widoku, zmodyfikuj RazorViewLocationFormats kolekcję . Aby na przykład wyszukać widoki w ścieżce /Components/{View Component Name}/{View Name}
, dodaj nowy element do kolekcji:
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.
W poprzednim kodzie symbol zastępczy {0}
reprezentuje ścieżkę Components/{View Component Name}/{View Name}
.
Wywoływanie składnika widoku
Aby użyć składnika widoku, wywołaj następujące elementy w widoku:
@await Component.InvokeAsync("Name of view component",
{Anonymous Type Containing Parameters})
Parametry są przekazywane do InvokeAsync
metody . Składnik PriorityList
widoku opracowany w artykule jest wywoływany z Views/ToDo/Index.cshtml
pliku widoku. W poniższym kodzie metoda jest wywoływana InvokeAsync
z dwoma parametrami:
</table>
<div>
Maximum Priority: @ViewData["maxPriority"] <br />
Is Complete: @ViewData["isDone"]
@await Component.InvokeAsync("PriorityList",
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
</div>
Wywoływanie składnika widoku jako pomocnika tagów
Składnik widoku można wywołać jako pomocnik tagów:
<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>
Parametry klasy i metody Pascal cased dla pomocników tagów są tłumaczone na ich przypadek kebab. Pomocnik tagów do wywoływania składnika widoku używa <vc></vc>
elementu . Składnik widoku jest określony w następujący sposób:
<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>
Aby użyć składnika widoku jako pomocnika tagów, zarejestruj zestaw zawierający składnik widoku przy użyciu @addTagHelper
dyrektywy . Jeśli składnik widoku znajduje się w zestawie o nazwie MyWebApp
, dodaj następującą dyrektywę _ViewImports.cshtml
do pliku:
@addTagHelper *, MyWebApp
Składnik widoku można zarejestrować jako pomocnik tagów do dowolnego pliku, który odwołuje się do składnika widoku. Aby uzyskać więcej informacji na temat rejestrowania pomocników tagów, zobacz Zarządzanie zakresem pomocnika tagów.
Metoda InvokeAsync
używana w tym samouczku:
@await Component.InvokeAsync("PriorityList",
new {
maxPriority = ViewData["maxPriority"],
isDone = ViewData["isDone"] }
)
W poprzednim znaczniku PriorityList
składnik widoku staje się .priority-list
Parametry składnika widoku są przekazywane jako atrybuty w przypadku kebab.
Wywoływanie składnika widoku bezpośrednio z kontrolera
Składniki widoku są zwykle wywoływane z widoku, ale mogą być wywoływane bezpośrednio z metody kontrolera. Chociaż składniki widoku nie definiują punktów końcowych, takich jak kontrolery, można zaimplementować akcję kontrolera zwracającą zawartość obiektu ViewComponentResult
.
W poniższym przykładzie składnik widoku jest wywoływany bezpośrednio z kontrolera:
public IActionResult IndexVC(int maxPriority = 2, bool isDone = false)
{
return ViewComponent("PriorityList",
new {
maxPriority = maxPriority,
isDone = isDone
});
}
Tworzenie podstawowego składnika widoku
Pobierz, skompiluj i przetestuj kod początkowy. Jest to podstawowy projekt z kontrolerem ToDo
, który wyświetla listę elementów zadań do wykonania .
Aktualizowanie kontrolera w celu przekazania priorytetu i stanu ukończenia
Zaktualizuj metodę tak Index
, aby korzystała z parametrów stanu priorytetu i ukończenia:
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);
}
Dodawanie klasy ViewComponent
Dodaj klasę ViewComponent do elementu 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();
}
}
Uwagi dotyczące kodu:
Klasy składników widoku mogą być zawarte w dowolnym folderze w projekcie.
Ponieważ nazwa klasy PriorityListViewComponent kończy się sufiksem ViewComponent, środowisko uruchomieniowe używa ciągu
PriorityList
podczas odwoływania się do składnika klasy z widoku.Atrybut
[ViewComponent]
może zmienić nazwę używaną do odwołowania się do składnika widoku. Na przykład klasa mogła mieć nazwęXYZ
z następującym[ViewComponent]
atrybutem:[ViewComponent(Name = "PriorityList")] public class XYZ : ViewComponent
Atrybut
[ViewComponent]
w poprzednim kodzie informuje selektora składników widoku do użycia:- Nazwa
PriorityList
podczas wyszukiwania widoków skojarzonych z składnikiem - Ciąg "PriorityList" podczas odwoływania się do składnika klasy z widoku.
- Nazwa
Składnik używa iniekcji zależności, aby udostępnić kontekst danych.
InvokeAsync
Uwidacznia metodę, którą można wywołać z widoku, i może przyjmować dowolną liczbę argumentów.Metoda
InvokeAsync
zwraca zestawToDo
elementów spełniającychisDone
parametry imaxPriority
.
Tworzenie widoku składnika Razor
Utwórz folder Views/Shared/Components. Ten folder musi mieć nazwę Components.
Utwórz folder Views/Shared/Components/PriorityList. Ta nazwa folderu musi być zgodna z nazwą klasy składnika widoku lub nazwą klasy minus sufiks.
ViewComponent
Jeśli atrybut jest używany, nazwa klasy musi być zgodna z oznaczeniem atrybutu.Views/Shared/Components/PriorityList/Default.cshtml
Razor Utwórz widok:@model IEnumerable<ViewComponentSample.Models.TodoItem> <h3>Priority Items</h3> <ul> @foreach (var todo in Model) { <li>@todo.Name</li> } </ul>
Widok Razor przyjmuje listę
TodoItem
i wyświetla je. Jeśli metoda składnikaInvokeAsync
widoku nie przekazuje nazwy widoku, wartość Domyślna jest używana dla nazwy widoku zgodnie z konwencją. Aby zastąpić domyślny styl określonego kontrolera, dodaj widok do folderu widoku specyficznego dla kontrolera (na przykład Views/ToDo/Components/PriorityList/Default.cshtml)..Jeśli składnik widoku jest specyficzny dla kontrolera, można go dodać do folderu specyficznego dla kontrolera. Na przykład
Views/ToDo/Components/PriorityList/Default.cshtml
jest specyficzny dla kontrolera.div
Dodaj element zawierający wywołanie składnika listy priorytetów w dolnej częściViews/ToDo/index.cshtml
pliku:</table> <div> Maximum Priority: @ViewData["maxPriority"] <br /> Is Complete: @ViewData["isDone"] @await Component.InvokeAsync("PriorityList", new { maxPriority = ViewData["maxPriority"], isDone = ViewData["isDone"] } ) </div>
Znacznik @await Component.InvokeAsync
pokazuje składnię wywoływania składników widoku. Pierwszym argumentem jest nazwa składnika, który chcemy wywołać lub wywołać. Kolejne parametry są przekazywane do składnika. InvokeAsync
może przyjmować dowolną liczbę argumentów.
Testowanie aplikacji. Na poniższej ilustracji przedstawiono listę Zadań do wykonania i elementy priorytetu:
Składnik widoku można wywołać bezpośrednio z kontrolera:
public IActionResult IndexVC(int maxPriority = 2, bool isDone = false)
{
return ViewComponent("PriorityList",
new {
maxPriority = maxPriority,
isDone = isDone
});
}
Określanie nazwy składnika widoku
Składnik widoku złożonego może wymagać określenia widoku innego niż domyślny w niektórych warunkach. Poniższy kod pokazuje, jak określić widok "PVC" z InvokeAsync
metody . Zaktualizuj metodę InvokeAsync
PriorityListViewComponent
w klasie .
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);
}
Views/Shared/Components/PriorityList/Default.cshtml
Skopiuj plik do widoku o nazwie Views/Shared/Components/PriorityList/PVC.cshtml
. Dodaj nagłówek, aby wskazać, że widok PVC jest używany.
@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>
Uruchom aplikację i sprawdź widok PVC.
Jeśli widok PVC nie jest renderowany, sprawdź, czy składnik widoku o priorytecie 4 lub wyższym jest wywoływany.
Badanie ścieżki widoku
Zmień parametr priorytetu na trzy lub mniej, aby widok priorytetu nie został zwrócony.
Tymczasowo zmień nazwę elementu na
Views/ToDo/Components/PriorityList/Default.cshtml
1Default.cshtml
.Przetestuj aplikację, wystąpi następujący błąd:
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
Skopiuj folder
Views/ToDo/Components/PriorityList/1Default.cshtml
do folderuViews/Shared/Components/PriorityList/Default.cshtml
.Dodaj znaczniki do widoku składników udostępnionego widoku zadań do wykonania, aby wskazać, że widok pochodzi z folderu Udostępnione.
Przetestuj widok składników udostępnionych .
Unikaj zakodowanych ciągów
W przypadku bezpieczeństwa czasu kompilacji zastąp nazwę składnika widoku zakodowanego na podstawie kodu nazwą klasy. Zaktualizuj plik PriorityListViewComponent.cs, aby nie używał sufiksu "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();
}
}
Plik widoku :
</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>
Przeciążenie Component.InvokeAsync
metody, która przyjmuje typ CLR, używa typeof
operatora :
</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>
Wykonywanie pracy synchronicznej
Platforma obsługuje wywoływanie metody synchronicznej, jeśli praca asynchroniczna Invoke
nie jest wymagana. Poniższa metoda tworzy synchroniczny Invoke
składnik widoku:
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);
}
}
}
Plik składnika Razor widoku:
<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>
Składnik widoku jest wywoływany w Razor pliku (na przykład Views/Home/Index.cshtml
) przy użyciu jednego z następujących metod:
Aby użyć podejścia, wywołaj metodę IViewComponentHelper Component.InvokeAsync
:
@await Component.InvokeAsync(nameof(PriorityList),
new { maxPriority = 4, isDone = true })
Aby użyć pomocnika tagów, zarejestruj zestaw zawierający składnik widoku przy użyciu @addTagHelper
dyrektywy (składnik widoku znajduje się w zestawie o nazwie MyWebApp
):
@addTagHelper *, MyWebApp
Użyj pomocnika tagu składnika widoku w Razor pliku znaczników:
<vc:priority-list max-priority="999" is-done="false">
</vc:priority-list>
Sygnatura PriorityList.Invoke
metody metody jest synchroniczna, ale Razor znajduje i wywołuje metodę w Component.InvokeAsync
pliku znaczników.
Dodatkowe zasoby
Wyświetl lub pobierz przykładowy kod (jak pobrać)
Składniki widoku
Składniki widoku są podobne do widoków częściowych, ale są znacznie bardziej zaawansowane. Składniki widoku nie używają powiązania modelu i zależą tylko od danych dostarczonych podczas wywoływania. Ten artykuł został napisany przy użyciu kontrolerów i widoków, ale składniki wyświetlania również współpracują ze stronami Razor .
Składnik widoku:
- Renderuje fragment, a nie całą odpowiedź.
- Obejmuje te same kwestie związane z separacją i korzyściami z testowania znalezionymi między kontrolerem a widokiem.
- Może mieć parametry i logikę biznesową.
- Jest zwykle wywoływany ze strony układu.
Składniki widoku są przeznaczone w dowolnym miejscu, w którym logika renderowania wielokrotnego użytku jest zbyt złożona dla widoku częściowego, takiego jak:
- Menu nawigacji dynamicznej
- Tagowanie chmury (gdzie wysyła zapytanie do bazy danych)
- Panel logowania
- Koszyk
- Ostatnio opublikowane artykuły
- Zawartość paska bocznego w typowym blogu
- Panel logowania, który będzie renderowany na każdej stronie i wyświetla linki do wylogowania lub logowania, w zależności od stanu logowania użytkownika
Składnik widoku składa się z dwóch części: klasy (zazwyczaj pochodzącej z ViewComponentklasy ) i zwracany wynik (zazwyczaj widok). Podobnie jak kontrolery, składnik widoku może być poco, ale większość deweloperów korzysta z metod i właściwości dostępnych przez wyprowadzanie z ViewComponent
klasy .
Podczas rozważania, czy wyświetlanie składników spełnia specyfikacje aplikacji, rozważ użycie Razor składników. Razor składniki łączą również znaczniki z kodem C#, aby tworzyć jednostki interfejsu użytkownika wielokrotnego użytku. Razor składniki są zaprojektowane pod kątem produktywności deweloperów podczas zapewniania logiki i kompozycji interfejsu użytkownika po stronie klienta. Aby uzyskać więcej informacji, zobacz ASP.NET Podstawowe Razor składniki. Aby uzyskać informacje na temat dołączania Razor składników do aplikacji MVC lub Razor Pages, zobacz Integrowanie składników ASP.NET Core Razor z mvC lub Razor pages.
Tworzenie składnika widoku
Ta sekcja zawiera ogólne wymagania dotyczące tworzenia składnika widoku. W dalszej części artykułu szczegółowo sprawdzimy każdy krok i utworzymy składnik widoku.
Klasa składników widoku
Klasę składników widoku można utworzyć za pomocą dowolnego z następujących elementów:
- Wyprowadzanie z widokuComponent
- Dekorowanie klasy za pomocą atrybutu
[ViewComponent]
lub wyprowadzanie z klasy z atrybutem[ViewComponent]
- Tworzenie klasy, w której nazwa kończy się sufiksem ViewComponent
Podobnie jak kontrolery, składniki widoku muszą być publiczne, niezagnieżdżone i nie abstrakcyjne klasy. Nazwa składnika widoku to nazwa klasy z usuniętym sufiksem "ViewComponent". Można go również jawnie określić przy użyciu ViewComponentAttribute.Name
właściwości .
Klasa składników widoku:
- W pełni obsługuje wstrzykiwanie zależności konstruktora
- Nie bierze udziału w cyklu życia kontrolera, co oznacza, że nie można używać filtrów w składniku widoku
Aby zatrzymać klasę, która ma sufiks ViewComponent bez uwzględniania wielkości liter, jest traktowana jako składnik widoku, udekoruj klasę za pomocą atrybutu [NonViewComponent]:
[NonViewComponent]
public class ReviewComponent
{
// ...
Wyświetlanie metod składników
Składnik widoku definiuje logikę InvokeAsync
w metodzie zwracającej metodę Task<IViewComponentResult>
lub w metodzie synchronicznej Invoke
zwracającej IViewComponentResult
element . Parametry pochodzą bezpośrednio z wywołania składnika widoku, a nie z powiązania modelu. Składnik widoku nigdy nie obsługuje bezpośrednio żądania. Zazwyczaj składnik widoku inicjuje model i przekazuje go do widoku, wywołując metodę View
. Podsumowując, wyświetl metody składników:
- Zdefiniuj metodę
InvokeAsync
zwracającą metodęTask<IViewComponentResult>
synchronicznąInvoke
lub zwracającąIViewComponentResult
wartość . - Zazwyczaj inicjuje model i przekazuje go do widoku, wywołując metodę
ViewComponent
View
. - Parametry pochodzą z metody wywołującej, a nie z protokołu HTTP. Nie ma powiązania modelu.
- Nie są dostępne bezpośrednio jako punkt końcowy HTTP. Są one wywoływane z kodu (zwykle w widoku). Składnik widoku nigdy nie obsługuje żądania.
- Są przeciążone podpisem, a nie wszelkimi szczegółami z bieżącego żądania HTTP.
Wyświetlanie ścieżki wyszukiwania
Środowisko uruchomieniowe wyszukuje widok w następujących ścieżkach:
- /Views/{Nazwa kontrolera}/Składniki/{Wyświetl nazwę składnika}/{Nazwa widoku}
- /Views/Shared/Components/{Wyświetl nazwę składnika}/{Nazwa widoku}
- /Pages/Shared/Components/{Wyświetl nazwę składnika}/{Nazwa widoku}
- /Areas/{Nazwa obszaru}/Widoki/Udostępnione/Składniki/{Wyświetl nazwę składnika}/{Nazwa widoku}
Ścieżka wyszukiwania dotyczy projektów przy użyciu kontrolerów i widoków i Razor stron.
Domyślna nazwa widoku składnika widoku to Domyślna, co oznacza, że plik widoku będzie zazwyczaj miał nazwę Default.cshtml
. Podczas tworzenia wyniku składnika widoku lub wywoływania View
metody można określić inną nazwę widoku.
Zalecamy nadanie nazwy pliku Default.cshtml
widoku i użycie ścieżki Views/Shared/Components/{Wyświetl nazwę składnika}/{Nazwa widoku} . Składnik PriorityList
widoku używany w tym przykładzie jest używany Views/Shared/Components/PriorityList/Default.cshtml
dla widoku składnika widoku.
Dostosowywanie ścieżki wyszukiwania widoku
Aby dostosować ścieżkę wyszukiwania widoku, zmodyfikuj RazorViewLocationFormats kolekcję . Aby na przykład wyszukać widoki w ścieżce "/Components/{Wyświetl nazwę składnika}/{Nazwa widoku}", dodaj nowy element do kolekcji:
services.AddMvc()
.AddRazorOptions(options =>
{
options.ViewLocationFormats.Add("/{0}.cshtml");
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
W poprzednim kodzie symbol zastępczy "{0}" reprezentuje ścieżkę "Components/{View Component Name}/{View Component Name}/{View Name}".
Wywoływanie składnika widoku
Aby użyć składnika widoku, wywołaj następujące elementy w widoku:
@await Component.InvokeAsync("Name of view component", {Anonymous Type Containing Parameters})
Parametry zostaną przekazane do InvokeAsync
metody . Składnik PriorityList
widoku opracowany w artykule jest wywoływany z Views/ToDo/Index.cshtml
pliku widoku. W poniższych metoda jest wywoływana InvokeAsync
z dwoma parametrami:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
Wywoływanie składnika widoku jako pomocnika tagów
W przypadku ASP.NET Core 1.1 i nowszych można wywołać składnik widoku jako pomocnik tagów:
<vc:priority-list max-priority="2" is-done="false">
</vc:priority-list>
Parametry klasy i metody Pascal cased dla pomocników tagów są tłumaczone na ich przypadek kebab. Pomocnik tagów do wywoływania składnika widoku używa <vc></vc>
elementu . Składnik widoku jest określony w następujący sposób:
<vc:[view-component-name]
parameter1="parameter1 value"
parameter2="parameter2 value">
</vc:[view-component-name]>
Aby użyć składnika widoku jako pomocnika tagów, zarejestruj zestaw zawierający składnik widoku przy użyciu @addTagHelper
dyrektywy . Jeśli składnik widoku znajduje się w zestawie o nazwie MyWebApp
, dodaj następującą dyrektywę _ViewImports.cshtml
do pliku:
@addTagHelper *, MyWebApp
Składnik widoku można zarejestrować jako pomocnik tagów do dowolnego pliku, który odwołuje się do składnika widoku. Aby uzyskać więcej informacji na temat rejestrowania pomocników tagów, zobacz Zarządzanie zakresem pomocnika tagów.
Metoda InvokeAsync
używana w tym samouczku:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
W znacznikach pomocnika tagów:
<vc:priority-list max-priority="2" is-done="false">
</vc:priority-list>
W powyższym PriorityList
przykładzie składnik widoku staje się .priority-list
Parametry składnika widoku są przekazywane jako atrybuty w przypadku kebab.
Wywoływanie składnika widoku bezpośrednio z kontrolera
Składniki widoku są zwykle wywoływane z widoku, ale można wywołać je bezpośrednio z metody kontrolera. Chociaż składniki widoku nie definiują punktów końcowych, takich jak kontrolery, można łatwo zaimplementować akcję kontrolera zwracającą zawartość elementu ViewComponentResult
.
W tym przykładzie składnik widoku jest wywoływany bezpośrednio z kontrolera:
public IActionResult IndexVC()
{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
Przewodnik: tworzenie prostego składnika widoku
Pobierz, skompiluj i przetestuj kod początkowy. Jest to prosty projekt z kontrolerem ToDo
, który wyświetla listę elementów zadań do wykonania .
Dodawanie klasy ViewComponent
Utwórz folder ViewComponents i dodaj następującą PriorityListViewComponent
klasę:
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();
}
}
}
Uwagi dotyczące kodu:
Klasy składników widoku mogą być zawarte w dowolnym folderze w projekcie.
Ponieważ nazwa klasy PriorityListViewComponent kończy się sufiksem ViewComponent, środowisko uruchomieniowe używa ciągu
PriorityList
podczas odwoływania się do składnika klasy z widoku.Atrybut
[ViewComponent]
może zmienić nazwę używaną do odwołowania się do składnika widoku. Na przykład klasa mogła mieć nazwęXYZ
z atrybutemViewComponent
:[ViewComponent(Name = "PriorityList")] public class XYZ : ViewComponent
Atrybut
[ViewComponent]
w poprzednim kodzie informuje selektora składników widoku do użycia:- Nazwa
PriorityList
podczas wyszukiwania widoków skojarzonych z składnikiem - Ciąg "PriorityList" podczas odwoływania się do składnika klasy z widoku.
- Nazwa
Składnik używa iniekcji zależności, aby udostępnić kontekst danych.
InvokeAsync
Uwidacznia metodę, którą można wywołać z widoku, i może przyjmować dowolną liczbę argumentów.Metoda
InvokeAsync
zwraca zestawToDo
elementów spełniającychisDone
parametry imaxPriority
.
Tworzenie widoku składnika Razor
Utwórz folder Views/Shared/Components. Ten folder musi mieć nazwę
Components
.Utwórz folder Views/Shared/Components/PriorityList. Ta nazwa folderu musi być zgodna z nazwą klasy składnika widoku lub nazwą klasy minus sufiksem (jeśli przestrzegamy konwencji i użyto sufiksu ViewComponent w nazwie klasy). Jeśli użyto atrybutu
ViewComponent
, nazwa klasy musi być zgodna z oznaczeniem atrybutu.Views/Shared/Components/PriorityList/Default.cshtml
Razor Utwórz widok:@model IEnumerable<ViewComponentSample.Models.TodoItem> <h3>Priority Items</h3> <ul> @foreach (var todo in Model) { <li>@todo.Name</li> } </ul>
Widok Razor przyjmuje listę
TodoItem
i wyświetla je. Jeśli metoda składnikaInvokeAsync
widoku nie przekazuje nazwy widoku (jak w naszym przykładzie), wartość domyślna jest używana dla nazwy widoku według konwencji. W dalszej części samouczka pokażę, jak przekazać nazwę widoku. Aby zastąpić domyślny styl określonego kontrolera, dodaj widok do folderu widoku specyficznego dla kontrolera (na przykład Views/ToDo/Components/PriorityList/Default.cshtml)..Jeśli składnik widoku jest specyficzny dla kontrolera, możesz dodać go do folderu specyficznego dla kontrolera (
Views/ToDo/Components/PriorityList/Default.cshtml
).div
Dodaj element zawierający wywołanie składnika listy priorytetów w dolnej częściViews/ToDo/index.cshtml
pliku:</table> <div> @await Component.InvokeAsync("PriorityList", new { maxPriority = 2, isDone = false }) </div>
Znacznik @await Component.InvokeAsync
pokazuje składnię wywoływania składników widoku. Pierwszym argumentem jest nazwa składnika, który chcemy wywołać lub wywołać. Kolejne parametry są przekazywane do składnika. InvokeAsync
może przyjmować dowolną liczbę argumentów.
Testowanie aplikacji. Na poniższej ilustracji przedstawiono listę Zadań do wykonania i elementy priorytetu:
Składnik widoku można również wywołać bezpośrednio z kontrolera:
public IActionResult IndexVC()
{
return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
Określanie nazwy widoku
Składnik widoku złożonego może wymagać określenia widoku innego niż domyślny w niektórych warunkach. Poniższy kod pokazuje, jak określić widok "PVC" z InvokeAsync
metody . Zaktualizuj metodę InvokeAsync
PriorityListViewComponent
w klasie .
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);
}
Views/Shared/Components/PriorityList/Default.cshtml
Skopiuj plik do widoku o nazwie Views/Shared/Components/PriorityList/PVC.cshtml
. Dodaj nagłówek, aby wskazać, że widok PVC jest używany.
@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>
Aktualizacja Views/ToDo/Index.cshtml
:
@await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
Uruchom aplikację i sprawdź widok PVC.
Jeśli widok PVC nie jest renderowany, sprawdź, czy wywołujesz składnik widoku o priorytecie 4 lub wyższym.
Badanie ścieżki widoku
Zmień parametr priorytetu na trzy lub mniej, aby widok priorytetu nie został zwrócony.
Tymczasowo zmień nazwę elementu na
Views/ToDo/Components/PriorityList/Default.cshtml
1Default.cshtml
.Przetestuj aplikację. Zostanie wyświetlony następujący błąd:
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
Skopiuj folder
Views/ToDo/Components/PriorityList/1Default.cshtml
do folderuViews/Shared/Components/PriorityList/Default.cshtml
.Dodaj znaczniki do widoku składników udostępnionego widoku zadań do wykonania, aby wskazać, że widok pochodzi z folderu Udostępnione.
Przetestuj widok składników udostępnionych .
Unikanie zakodowanych ciągów
Jeśli chcesz, aby bezpieczeństwo czasu kompilacji było możliwe, możesz zastąpić nazwę składnika widoku zakodowanego na podstawie kodu nazwą klasy. Utwórz składnik widoku bez sufiksu "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();
}
}
}
Dodaj instrukcję using
do Razor pliku widoku i użyj nameof
operatora :
@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>
Można użyć przeciążenia Component.InvokeAsync
metody, która przyjmuje typ CLR. Pamiętaj, aby użyć typeof
operatora w tym przypadku:
@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>
Wykonywanie pracy synchronicznej
Platforma obsługuje wywoływanie metody synchronicznej Invoke
, jeśli nie trzeba wykonywać pracy asynchronicznej. Poniższa metoda tworzy synchroniczny Invoke
składnik widoku:
public class PriorityList : ViewComponent
{
public IViewComponentResult Invoke(int maxPriority, bool isDone)
{
var items = new List<string> { $"maxPriority: {maxPriority}", $"isDone: {isDone}" };
return View(items);
}
}
Plik składnika Razor widoku zawiera listę ciągów przekazanych do Invoke
metody (Views/Home/Components/PriorityList/Default.cshtml
):
@model List<string>
<h3>Priority Items</h3>
<ul>
@foreach (var item in Model)
{
<li>@item</li>
}
</ul>
Składnik widoku jest wywoływany w Razor pliku (na przykład Views/Home/Index.cshtml
) przy użyciu jednego z następujących metod:
Aby użyć podejścia, wywołaj metodę IViewComponentHelper Component.InvokeAsync
:
@await Component.InvokeAsync(nameof(PriorityList), new { maxPriority = 4, isDone = true })
Aby użyć pomocnika tagów, zarejestruj zestaw zawierający składnik widoku przy użyciu @addTagHelper
dyrektywy (składnik widoku znajduje się w zestawie o nazwie MyWebApp
):
@addTagHelper *, MyWebApp
Użyj pomocnika tagu składnika widoku w Razor pliku znaczników:
<vc:priority-list max-priority="999" is-done="false">
</vc:priority-list>
Sygnatura PriorityList.Invoke
metody metody jest synchroniczna, ale Razor znajduje i wywołuje metodę w Component.InvokeAsync
pliku znaczników.
Wszystkie parametry składnika widoku są wymagane
Każdy parametr w składniku widoku jest wymaganym atrybutem. Zobacz ten problem z usługą GitHub. Jeśli pominięto jakikolwiek parametr:
- Sygnatura
InvokeAsync
metody nie będzie zgodna, dlatego metoda nie zostanie wykonana. - Element ViewComponent nie będzie renderować żadnych znaczników.
- Nie zostaną rzucone żadne błędy.