Zobrazit součásti v ASP.NET Core

Autor: Rick Anderson

Zobrazit nebo stáhnout ukázkový kód (Jak stáhnout)

Komponenty zobrazení

Zobrazení součástí se podobá částečným zobrazením, ale jsou mnohem výkonnější. Zobrazení komponent nepoužívá vazbu modelu a závisí pouze na datech poskytnutých při jejich volání. Tento článek se napsal pomocí řadičů a zobrazení, ale komponenty můžete zobrazit i na Razor stránkách.

Součást zobrazení:

  • Vykreslí blok dat, nikoli celou odpověď.
  • Zahrnuje stejné výhody a testování, které byly nalezeny mezi kontrolkou a zobrazením.
  • Může mít parametry a obchodní logiku.
  • Je obvykle vyvolána ze stránky rozložení.

Zobrazit součásti jsou určeny kdekoli, kde máte opakovaně použitelnou logiku vykreslování, která je příliš složitá pro částečné zobrazení, například:

  • Dynamické navigační nabídky
  • Označení cloudu (kde se dotazuje databáze)
  • Panel přihlášení
  • Nákupní košík
  • Nedávno publikované články
  • Obsah bočního panelu na typickém blogu
  • Přihlašovací panel, který se vykreslí na každé stránce, a zobrazí buď odkazy pro odhlášení nebo přihlášení, v závislosti na stavu přihlášení uživatele.

Součást zobrazení se skládá ze dvou částí: třídy (obvykle odvozené od ViewComponent) a výsledek, který vrátí (obvykle zobrazení). Podobně jako řadiče se může jednat o součást zobrazení POCO, ale většina vývojářů bude chtít využít metody a vlastnosti, které jsou k dispozici odvozením z ViewComponent .

Při zvažování, zda zobrazit součásti vyhovují specifikacím aplikace, zvažte Razor místo toho použití součástí. Razor komponenty také kombinují značky s kódem jazyka C# pro vytváření opakovaně použitelných jednotek uživatelského rozhraní. Razor komponenty jsou navržené pro produktivitu vývojářů při poskytování logiky uživatelského rozhraní a způsobu složení na straně klienta. Další informace naleznete v tématu RazorASP.NET Core Součásti. Informace o tom, jak začlenit Razor komponenty do aplikace MVC nebo Razor Pages, najdete v tématu Předběžné vykreslení a integrace ASP.NET Core Razor komponent .

Vytvoření komponenty zobrazení

Tato část obsahuje požadavky na vysoké úrovni pro vytvoření komponenty zobrazení. Později v tomto článku probereme podrobný přehled jednotlivých kroků a vytvoříme pohledovou komponentu.

Třída zobrazení součásti

Třídu zobrazení komponenty lze vytvořit pomocí kterékoli z následujících možností:

  • Odvození z ViewComponent
  • Upravení třídu s [ViewComponent] atributem nebo odvozením z třídy s [ViewComponent] atributem.
  • Vytvoření třídy, kde název končí příponou ViewComponent

Stejně jako řadiče musí být zobrazení součásti veřejné, nevnořené a neabstraktní třídy. Název komponenty zobrazení je název třídy s odebraným příponou "ViewComponent". Dá se taky explicitně zadat pomocí ViewComponentAttribute.Name Vlastnosti.

Třída zobrazení komponenty:

  • Plně podporuje vkládání závislostí konstruktoru

  • Netrvá v životním cyklu kontroléru, což znamená, že nemůžete použít filtry v součásti zobrazení

Zobrazit metody komponenty

Komponenta zobrazení definuje svou logiku v InvokeAsync metodě, která vrací Task<IViewComponentResult> nebo v synchronní Invoke metodě, která vrací IViewComponentResult . Parametry přicházejí přímo z vyvolání součásti zobrazení, nikoli z vazby modelu. Součást zobrazení nikdy nezpracovává požadavek přímo. Obvykle komponenta zobrazení inicializuje model a předá ho zobrazení voláním View metody. V části Souhrn si prohlédněte metody komponenty:

  • Definujte InvokeAsync metodu, která vrátí Task<IViewComponentResult> nebo synchronní Invoke metodu, která vrátí IViewComponentResult .
  • Obvykle inicializuje model a předá ho zobrazení voláním ViewComponent View metody.
  • Parametry pocházejí z volající metody, nikoli HTTP. Neexistuje žádná vazba modelu.
  • Nejsou dostupné přímo jako koncový bod HTTP. Jsou vyvolány z vašeho kódu (obvykle v zobrazení). Součást zobrazení nikdy nezpracovává požadavek.
  • Jsou v signatuře přetížené místo jakýchkoli podrobností z aktuální žádosti HTTP.

Zobrazit cestu pro hledání

Modul runtime vyhledává zobrazení v následujících cestách:

  • /Views/{Controller} název součásti/Components/{View}/{View}
  • Název součásti/Views/Shared/Components/{View}/{View}
  • Název součásti/Pages/Shared/Components/{View}/{View}

Cesta pro hledání se vztahuje na projekty pomocí řadičů a zobrazení a Razor stránek.

Výchozí název zobrazení pro součást zobrazení je výchozí, což znamená, že váš soubor zobrazení bude obvykle pojmenovaný Default. cshtml. Při vytváření výsledku zobrazení součásti nebo při volání metody lze zadat jiný název zobrazení View .

Doporučujeme pojmenovat soubor zobrazení Default. cshtml a použít cestu views /Shared/Components/{View Component Name}/{View Name} . PriorityListKomponenta zobrazení použitá v tomto příkladu používá zobrazení /Shared/Components/PriorityList/default. cshtml pro zobrazení součástí zobrazení.

Přizpůsobení cesty hledání zobrazení

Chcete-li přizpůsobit cestu pro vyhledávání zobrazení Razor , ViewLocationFormats kolekci úprav. Chcete-li například vyhledat zobrazení v cestě "/Components/{View název součásti}/{View Name}", přidejte novou položku do kolekce:

services.AddMvc()
    .AddRazorOptions(options =>
    {
        options.ViewLocationFormats.Add("/{0}.cshtml");
    })
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

V předchozím kódu zástupný symbol " {0} " představuje cestu "Components/{View Component Name}/{View Name}".

Vyvolání komponenty zobrazení

Chcete-li použít součást zobrazení, zavolejte v rámci zobrazení následující:

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

Parametry budou předány InvokeAsync metodě. PriorityListSoučást zobrazení vyvinutá v článku se vyvolá z zobrazení zobrazení /TODO/index. cshtml . V následujícím InvokeAsync postupu je metoda volána se dvěma parametry:

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

Vyvolání komponenty zobrazení jako pomocné rutiny značky

pro ASP.NET Core 1,1 a vyšší můžete vyvolat součást zobrazení jako pomocníka značky:

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

Parametry třídy a metody použita jazyka Pascal pro pomocníky značek jsou přeloženy do jejich kebabho případu. Pomocný pomocník značek k vyvolání komponenty zobrazení používá <vc></vc> element. Součást zobrazení je určena následujícím způsobem:

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

Chcete-li použít zobrazení komponenty jako pomocníka značky, zaregistrujte sestavení obsahující komponentu zobrazení pomocí @addTagHelper direktivy. Pokud je vaše součást zobrazení v sestavení s názvem MyWebApp , přidejte následující direktivu do souboru _ViewImports. cshtml :

@addTagHelper *, MyWebApp

Můžete zaregistrovat součást zobrazení jako pomocný modul značek pro libovolný soubor, který odkazuje na součást zobrazení. Další informace o registraci pomocných rutin značek najdete v tématu Správa oboru pomocných značek .

InvokeAsyncMetoda použitá v tomto kurzu:

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

Značka pomocníka značky:

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

V ukázce výše se PriorityList zobrazí součást zobrazení priority-list . Parametry pro zobrazení komponenty jsou předány jako atributy v případě kebab.

Vyvolání komponenty zobrazení přímo z kontroleru

Zobrazení komponent se obvykle vyvolají ze zobrazení, ale můžete je vyvolat přímo z metody kontroleru. Přestože funkce View Components nedefinuje koncové body jako řadiče, můžete snadno implementovat akci kontroleru, která vrací obsah ViewComponentResult .

V tomto příkladu je součást zobrazení volána přímo z kontroleru:

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

Návod: Vytvoření jednoduché součásti zobrazení

Stažení, sestavení a otestování počátečního kódu. Jedná se o jednoduchý projekt s ToDo řadičem, který zobrazuje seznam položek TODO .

Seznam ToDo

Přidat třídu ViewComponent

Vytvořte složku ViewComponents a přidejte následující PriorityListViewComponent třídu:

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

Poznámky k kódu:

  • Třídy komponent zobrazení mohou být obsaženy v libovolné složce v projektu.

  • Vzhledem k tomu, že název třídy PriorityList ViewComponent končí příponou ViewComponent, použije modul runtime při odkazování na komponentu třídy ze zobrazení řetězec "PriorityList". Podrobněji to vysvětlím později.

  • Atribut [ViewComponent] může změnit název použitý pro odkaz na komponentu zobrazení. Mohli jsme například pojmenovat třídu a XYZ použít ViewComponent atribut :

    [ViewComponent(Name = "PriorityList")]
       public class XYZ : ViewComponent
    
  • Výše uvedený atribut říká selektoru součásti zobrazení, aby při hledání zobrazení přidružených k komponentě a použití řetězce [ViewComponent] "PriorityList" při odkazování na komponentu třídy PriorityList ze zobrazení. Podrobněji to vysvětlím později.

  • Komponenta používá injektáž závislostí, aby byl kontext dat k dispozici.

  • InvokeAsync zpřístupňuje metodu, kterou lze volat ze zobrazení, a může mít libovolný počet argumentů.

  • Metoda InvokeAsync vrátí sadu ToDo položek, které splňují parametry isDone a maxPriority .

Vytvoření zobrazení součástí Razor zobrazení

  • Vytvořte složku Views/Shared/Components. Tato složka musí mít název Components.

  • Vytvořte složku Views/Shared/Components/PriorityList. Tento název složky se musí shodovat s názvem třídy komponent zobrazení nebo názvem třídy minus příponou (pokud jsme použili konvenci a použili příponu ViewComponent v názvu třídy). Pokud byste ViewComponent použili atribut , název třídy by se měl shodovat s označením atributu.

  • Vytvořte zobrazení Views/Shared/Components/PriorityList/Default.cshtml: Razor

    @model IEnumerable<ViewComponentSample.Models.TodoItem>
    
    <h3>Priority Items</h3>
    <ul>
        @foreach (var todo in Model)
        {
            <li>@todo.Name</li>
        }
    </ul>
    

    Zobrazení Razor vezme seznam a zobrazí TodoItem je. Pokud metoda komponenty zobrazení nepřidá název zobrazení (jako v naší ukázce), použije se pro název zobrazení podle konvence výchozí InvokeAsync hodnota. Později v tomto kurzu vám ukážeme, jak předat název zobrazení. Pokud chcete přepsat výchozí styl určitého kontroleru, přidejte zobrazení do složky zobrazení specifické pro kontroler (například Views/ToDo/Components/PriorityList/Default.cshtml).

    Pokud je komponenta zobrazení specifická pro kontroler, můžete ji přidat do složky specifické pro kontroler (Views/ToDo/Components/PriorityList/Default.cshtml).

  • Na div konec souboru Views/ToDo/index.cshtml přidejte obsahující volání komponenty seznamu priorit:

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

Kód ukazuje @await Component.InvokeAsync syntaxi pro volání komponent zobrazení. Prvním argumentem je název komponenty, kterou chceme vyvolat nebo zavolat. Další parametry se předá komponentě. InvokeAsync může mít libovolný počet argumentů.

Otestujete aplikaci. Následující obrázek ukazuje seznam úkolů a položky priority:

položky seznamu úkolů a priority

Komponentu zobrazení můžete také volat přímo z kontroleru:

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

priority items from IndexVC action

Zadání názvu zobrazení

Komponenta komplexního zobrazení může za určitých podmínek zadat jiné než výchozí zobrazení. Následující kód ukazuje, jak zadat zobrazení PVC z InvokeAsync metody . Aktualizujte InvokeAsync metodu ve PriorityListViewComponent třídě .

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

Zkopírujte soubor Views/Shared/Components/PriorityList/Default.cshtml do zobrazení s názvem Views/Shared/Components/PriorityList/PVC.cshtml. Přidejte nadpis, který označuje, že se používá zobrazení PVC.

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

Aktualizace views/ToDo/Index.cshtml:

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

Spusťte aplikaci a ověřte zobrazení PVC.

Komponenta Zobrazení priority

Pokud se zobrazení PVC nevykreslí, ověřte, že voláte komponentu zobrazení s prioritou 4 nebo vyšší.

Prozkoumání cesty zobrazení

  • Změňte parametr priority na tři nebo méně, aby se zobrazení priority nevrátilo.

  • Dočasně přejmenujte Views/ToDo/Components/PriorityList/Default.cshtml na 1Default.cshtml.

  • Otestujte aplikaci, zobrazí se následující chyba:

    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
    
  • Zkopírujte Views/ToDo/Components/PriorityList/1Default.cshtml do Views/Shared/Components/PriorityList/Default.cshtml.

  • Do zobrazení součástí zobrazení Sdílené toDo přidejte nějaký kód, který bude indikovat, že zobrazení pochází ze sdílené složky.

  • Otestujte zobrazení sdílené součásti.

Výstup toDo se zobrazením sdílených komponent

Vyhněte se řetězcům s pevným kódem

Pokud chcete zkompilovat časovou bezpečnost, můžete nahradit název komponenty s pevným zobrazením názvem třídy. Vytvořte komponentu zobrazení bez přípony 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();
        }
    }
}

Do souboru using zobrazení přidejte příkaz a Razor použijte operátor nameof :

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

Můžete použít přetížení Component.InvokeAsync metody, která přebírá typ CLR. V tomto případě nezapomeňte typeof použít operátor :

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

Provedení synchronní práce

Rozhraní zpracovává volání synchronní metody, pokud nepotřebujete Invoke provádět asynchronní práci. Následující metoda vytvoří komponentu Invoke synchronního zobrazení:

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

Soubor komponenty zobrazení obsahuje seznam řetězců předáovaných metodě Razor Invoke (Views/ Home /Components/PriorityList/Default.cshtml):

@model List<string>

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

Komponenta view se vyvolá v souboru Razor (například Views/ Home /Index.cshtml) pomocí jednoho z následujících přístupů:

Pokud chcete použít IViewComponentHelper tento přístup, zavolejte Component.InvokeAsync :

Komponenta view se vyvolá v souboru Razor (například Views/ Home /Index.cshtml) s IViewComponentHelper .

Volání Component.InvokeAsync :

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

Pokud chcete použít pomocného prvku značek, zaregistrujte sestavení obsahující komponentu View pomocí direktivy (součást zobrazení @addTagHelper je v sestavení s názvem MyWebApp ):

@addTagHelper *, MyWebApp

V souboru značek použijte pomocná prvek značky Razor komponenty zobrazení:

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

Signatura metody metody PriorityList.Invoke je synchronní, ale vyhledá a Razor volá metodu s v souboru Component.InvokeAsync značek.

Všechny parametry součástí zobrazení jsou povinné.

Každý parametr v komponentě zobrazení je povinný atribut. Podívejte se na tento GitHub problém. Pokud je některý parametr vynechán:

  • Podpis InvokeAsync metody se neshoduje, proto se metoda nebude provádět.
  • Komponenta ViewComponent nevykreslí žádné značky.
  • Nebudou vyvolány žádné chyby.

Další zdroje informací