Delen via


Onderdelen weergeven in ASP.NET Core

Door Rick Anderson

Onderdelen weergeven

Weergaveonderdelen zijn vergelijkbaar met gedeeltelijke weergaven, maar ze zijn veel krachtiger. Onderdelen weergeven maken geen gebruik van modelbinding, ze zijn afhankelijk van de gegevens die worden doorgegeven bij het aanroepen van het weergaveonderdeel. Dit artikel is geschreven met behulp van controllers en Views, maar viewcomponenten werken met Razor Pagina's.

Een weergaveonderdeel:

  • Geeft een segment weer in plaats van een geheel antwoord.
  • Bevat dezelfde scheiding van verantwoordelijkheden en testbaarheidsvoordelen tussen een controller en view.
  • Kan parameters en bedrijfslogica hebben.
  • Wordt meestal aangeroepen vanaf een indelingspagina.

Weergaveonderdelen zijn bedoeld voor herbruikbare renderinglogica die te complex is voor een gedeeltelijke weergave, zoals:

  • Dynamische navigatiemenu's
  • Tag cloud, waar query's worden uitgevoerd op de database
  • Aanmeldingsvenster
  • Winkelwagen
  • Onlangs gepubliceerde artikelen
  • Sidebar-inhoud op een blog
  • Een aanmeldingsvenster dat op elke pagina wordt weergegeven en de koppelingen voor afmelden of aanmelden weergeven, afhankelijk van de aanmeldingsstatus van de gebruiker

Een weergaveonderdeel bestaat uit twee delen:

  • De klasse, meestal afgeleid van ViewComponent
  • Het resultaat dat wordt geretourneerd, meestal een weergave.

Net als controllers kan een weergaveonderdeel een POCO zijn, maar de meeste ontwikkelaars profiteren van de methoden en eigenschappen die beschikbaar zijn door af te leiden van ViewComponent.

Wanneer u overweegt om onderdelen weer te geven die voldoen aan de specificaties van een app, kunt u in plaats daarvan onderdelen gebruiken Razor . Razor onderdelen combineren ook markeringen met C#-code om herbruikbare UI-eenheden te produceren. Razor onderdelen zijn ontworpen voor productiviteit van ontwikkelaars bij het leveren van gebruikersinterfacelogica en -samenstelling aan de clientzijde. Zie ASP.NET Core Razor-onderdelenvoor meer informatie. Zie RazorRazor Pages-app.Razor

Een weergaveonderdeel maken

Deze sectie bevat de algemene vereisten voor het maken van een weergaveonderdeel. Later in het artikel zullen we elke stap in detail onderzoeken en een weergavecomponent maken.

De weergaveonderdeelklasse

Een weergaveonderdeelklasse kan op een van de volgende manieren worden gemaakt:

  • Afgeleid van ViewComponent
  • Een klasse decoreren met het [ViewComponent] kenmerk of afgeleid van een klasse met het [ViewComponent] kenmerk
  • Een klasse maken waarin de naam eindigt met het achtervoegsel ViewComponent

Net als controllers moeten weergaveonderdelen openbare, niet-geneste en niet-abstracte klassen zijn. De naam van het weergaveonderdeel is de klassenaam waarbij het ViewComponent achtervoegsel is verwijderd. Het kan ook expliciet worden opgegeven met behulp van de Name eigenschap.

Een weergaveonderdeelklasse:

Als u wilt voorkomen dat een klasse met een niet-hoofdlettergevoelig ViewComponent achtervoegsel wordt behandeld als een weergaveonderdeel, moet u de klasse voorzien van het [NonViewComponent] kenmerk:

using Microsoft.AspNetCore.Mvc;

[NonViewComponent]
public class ReviewComponent
{
    public string Status(string name) => JobStatus.GetCurrentStatus(name);
}

Onderdeelmethoden weergeven

Een weergaveonderdeel definieert de logica in een:

  • InvokeAsync methode die retourneert Task<IViewComponentResult>.
  • Invoke een methode die synchroon een IViewComponentResult retourneert.

Parameters zijn rechtstreeks afkomstig van aanroep van het weergaveonderdeel, niet van modelbinding. Een weergaveonderdeel verwerkt nooit rechtstreeks een aanvraag. Normaal gesproken initialiseert een weergaveonderdeel een model en geeft dit door aan een weergave door de View methode aan te roepen. Kortom, bekijk de methoden voor componenten.

  • Definieer een InvokeAsync methode die een Task<IViewComponentResult> of een synchrone Invoke methode retourneert die een IViewComponentResult.
  • Initialiseert een model doorgaans en geeft het door aan een weergave door de methode ViewComponent.View aan te roepen.
  • Parameters zijn afkomstig van de aanroepmethode, niet van HTTP. Er is geen modelbinding.
  • Zijn niet rechtstreeks bereikbaar als een HTTP-eindpunt. Ze worden meestal aangeroepen in een weergave. Een weergaveonderdeel verwerkt nooit een aanvraag.
  • Worden overbelast op de handtekening in plaats van details van de huidige HTTP-aanvraag.

Zoekpad weergeven

De runtime zoekt naar de weergave in de volgende paden:

  • /Views/{Controller Name}/Components/{View Component Name}/{View Name}
  • /Views/Shared/Components/{View Component Name}/{View Name}
  • /Pages/Shared/Components/{View Component Name}/{View Name}
  • /Areas/{Area Name}/Views/Shared/Components/{View Component Name}/{View Name}

Het zoekpad is van toepassing op projecten die controllers, weergaven en Razor pagina's gebruiken.

De standaardweergavenaam voor een weergaveonderdeel is Default, wat betekent dat weergavebestanden doorgaans de naam Default.cshtmlhebben. Er kan een andere weergavenaam worden opgegeven bij het maken van het resultaat van het weergaveonderdeel of bij het aanroepen van de View methode.

U wordt aangeraden het weergavebestand Default.cshtml een naam te geven en het pad Views/Shared/Components/{View Component Name}/{View Name} te gebruiken. Het PriorityList weergavecomponent dat in dit voorbeeld wordt gebruikt, gebruikt Views/Shared/Components/PriorityList/Default.cshtml voor de weergavecomponentweergave.

Het zoekpad voor weergave aanpassen

Wijzig de Razor-verzameling van ViewLocationFormats om het zoekpad te personaliseren. Als u bijvoorbeeld wilt zoeken naar weergaven binnen het pad /Components/{View Component Name}/{View Name}, voegt u een nieuw item toe aan de verzameling:

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.

In de voorgaande code vertegenwoordigt de tijdelijke aanduiding {0} het pad Components/{View Component Name}/{View Name}.

Een weergaveonderdeel aanroepen

Als u het weergaveonderdeel wilt gebruiken, roept u het volgende aan in een weergave:

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

De parameters worden doorgegeven aan de InvokeAsync methode. Het PriorityList weergaveonderdeel dat in het artikel is ontwikkeld, wordt aangeroepen vanuit het Views/ToDo/Index.cshtml weergavebestand. In de volgende code wordt de InvokeAsync methode aangeroepen met twee parameters:

</table>

<div>
    Maximum Priority: @ViewData["maxPriority"] <br />
    Is Complete:  @ViewData["isDone"]
    @await Component.InvokeAsync("PriorityList",
                     new { 
                         maxPriority =  ViewData["maxPriority"],
                         isDone = ViewData["isDone"]  }
                     )
</div>

Een weergavecomponent aanroepen als Tag Helper

Een weergaveonderdeel kan worden aangeroepen als een Tag Helper:

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

Pascal-cased klasse- en methodeparameters voor Tag Helpers worden omgezet in hun kebab case. De Tag Helper voor het aanroepen van een weergaveonderdeel maakt gebruik van het <vc></vc> element. Het weergaveonderdeel wordt als volgt opgegeven:

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

Als u een weergaveonderdeel wilt gebruiken als Tag Helper, registreert u de assembly met het weergaveonderdeel met behulp van de @addTagHelper instructie. Als het weergaveonderdeel zich in een assembly bevindt met de naam MyWebApp, voegt u de volgende instructie toe aan het _ViewImports.cshtml bestand:

@addTagHelper *, MyWebApp

Een weergaveonderdeel kan worden geregistreerd als Tag Helper voor elk bestand dat verwijst naar het weergaveonderdeel. Zie Tag Helper-bereik beheren voor meer informatie over het registreren van Tag Helpers.

De InvokeAsync methode die in deze handleiding wordt gebruikt:

@await Component.InvokeAsync("PriorityList",
                 new { 
                     maxPriority =  ViewData["maxPriority"],
                     isDone = ViewData["isDone"]  }
                 )

In de voorgaande markeringen wordt de PriorityList-weergavecomponent priority-list. De parameters voor het weergavecomponent worden doorgegeven als attributen in kebab-case.

Een weergaveonderdeel rechtstreeks vanuit een controller aanroepen

Weergaveonderdelen worden doorgaans aangeroepen vanuit een weergave, maar ze kunnen rechtstreeks vanuit een controllermethode worden aangeroepen. Hoewel weergaveonderdelen geen eindpunten zoals controllers definiëren, kan een controlleractie die de inhoud van een bestand ViewComponentResult retourneert, worden geïmplementeerd.

In het volgende voorbeeld wordt het weergaveonderdeel rechtstreeks vanuit de controller aangeroepen:

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

Een basisweergaveonderdeel maken

Download, bouw en test de starterscode. Het is een basisproject met een ToDo controller waarmee een lijst met taken wordt weergegeven.

Lijst met ToDos

De controller bijwerken om de prioriteit en voltooiingsstatus door te geven

Werk de methode bij voor het Index gebruik van parameters voor prioriteits- en voltooiingsstatus:

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

Een ViewComponent-klasse toevoegen

Voeg een ViewComponent-klasse toe aan 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();
    }
}

Opmerkingen over de code:

  • Weergavecomponentklassen kunnen zich in elke map in het project bevinden.

  • Omdat de klassenaam PriorityListViewComponent eindigt met het achtervoegsel ViewComponent, gebruikt de runtime de tekenreeks PriorityList bij het verwijzen naar het klasseonderdeel vanuit een weergave.

  • Het [ViewComponent] kenmerk kan de naam wijzigen die wordt gebruikt om te verwijzen naar een weergaveonderdeel. De klasse had bijvoorbeeld kunnen zijn genoemd XYZ met het volgende [ViewComponent] attribuut:

    [ViewComponent(Name = "PriorityList")]
       public class XYZ : ViewComponent
    
  • Het [ViewComponent] kenmerk in de voorgaande code geeft aan dat de viewcomponentselector gebruikt moet worden:

    • De naam PriorityList bij het zoeken naar de weergaven die aan de component zijn gekoppeld
    • De tekenreeks PriorityList bij het verwijzen naar het klasseonderdeel vanuit een weergave.
  • Het onderdeel maakt gebruik van afhankelijkheidsinjectie om de gegevenscontext beschikbaar te maken.

  • InvokeAsync maakt een methode beschikbaar die vanuit een weergave kan worden aangeroepen en kan een willekeurig aantal argumenten duren.

  • De InvokeAsync methode retourneert de set ToDo items die voldoen aan de isDone en maxPriority parameters.

Maak de weergavecomponent Razor

  • Maak de map Views/Shared/Components . Deze map moet de naam Components hebben.

  • Maak de map Views/Shared/Components/PriorityList . Deze mapnaam moet overeenkomen met de naam van de weergaveonderdeelklasse of de naam van de klasse minus het achtervoegsel. Als het ViewComponent kenmerk wordt gebruikt, moet de klassenaam overeenkomen met de kenmerkaanduiding.

  • Views/Shared/Components/PriorityList/Default.cshtml Razor Een weergave maken:

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

    De Razor weergave neemt een lijst van TodoItem en geeft deze weer. Als de weergaveonderdeelmethode InvokeAsync de naam van de weergave niet doorgeeft, wordt standaard gebruikt voor de weergavenaam op conventie. Als u de standaardstijl voor een specifieke controller wilt overschrijven, voegt u een weergave toe aan de controllerspecifieke weergavemap (bijvoorbeeld Weergaven/ToDo/Components/PriorityList/Default.cshtml).

    Als het weergaveonderdeel controllerspecifiek is, kan het worden toegevoegd aan de controllerspecifieke map. Is bijvoorbeeld Views/ToDo/Components/PriorityList/Default.cshtml controllerspecifiek.

  • Voeg een div bestand met een aanroep toe aan het onderdeel prioriteitslijst onderaan het Views/ToDo/index.cshtml bestand:

    </table>
    
    <div>
        Maximum Priority: @ViewData["maxPriority"] <br />
        Is Complete:  @ViewData["isDone"]
        @await Component.InvokeAsync("PriorityList",
                         new { 
                             maxPriority =  ViewData["maxPriority"],
                             isDone = ViewData["isDone"]  }
                         )
    </div>
    

De markering @await Component.InvokeAsync toont de syntaxis voor het aanroepen van weergaveonderdelen. Het eerste argument is de naam van het onderdeel dat we willen aanroepen of oproepen. Volgende parameters worden doorgegeven aan het onderdeel. InvokeAsync kan een willekeurig aantal argumenten aannemen.

De app testen. In de volgende afbeelding ziet u de takenlijst en de prioriteitsitems:

takenlijst en prioriteitsitems

Het weergaveonderdeel kan rechtstreeks vanuit de controller worden aangeroepen:

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

prioriteitsitems uit de indexVC-actie

Geef een weergaveonderdeelnaam op

Een onderdeel voor een complexe weergave moet mogelijk een niet-standaardweergave opgeven onder bepaalde omstandigheden. De volgende code laat zien hoe u de 'PVC'-weergave opgeeft vanuit de InvokeAsync methode. Werk de InvokeAsync methode in de PriorityListViewComponent klasse bij.

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

Kopieer het Views/Shared/Components/PriorityList/Default.cshtml bestand naar een weergave met de naam Views/Shared/Components/PriorityList/PVC.cshtml. Voeg een kop toe om aan te geven dat de PVC-weergave wordt gebruikt.

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

Voer de app uit en controleer de PVC-weergave.

Onderdeel Prioriteitsweergave

Als de PVC-weergave niet wordt weergegeven, controleert u of het weergaveonderdeel met een prioriteit van 4 of hoger wordt aangeroepen.

Het weergavepad onderzoeken

  • Wijzig de prioriteitsparameter in drie of minder, zodat de prioriteitsweergave niet wordt geretourneerd.

  • Wijzig de naam van het Views/ToDo/Components/PriorityList/Default.cshtml item tijdelijk in 1Default.cshtml.

  • Test de app, de volgende fout treedt op:

    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
    
  • Kopieer Views/ToDo/Components/PriorityList/1Default.cshtml naar Views/Shared/Components/PriorityList/Default.cshtml.

  • Voeg een aantal markeringen toe aan de Gedeelde takenlijst onderdeelweergave om aan te geven dat de weergave afkomstig is uit de Gedeelde map.

  • Test de weergave Gedeeld onderdeel .

ToDo-uitvoer met de weergave Gedeeld onderdeel

Vermijd vastgelegde tekenreeksen

Vervang de naam van het in code vastgelegde weergaveonderdeel door de klassenaam voor de veiligheid van de compilatietijd. Werk het PriorityListViewComponent.cs-bestand bij om het achtervoegsel ViewComponent niet te gebruiken:

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

Het weergavebestand:

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

Een overbelasting van de Component.InvokeAsync methode die een CLR-type gebruikt, maakt gebruik van de typeof operator:

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

Synchroon werk uitvoeren

Het framework verwerkt het aanroepen van een synchrone Invoke methode als asynchroon werk niet vereist is. Met de volgende methode maakt u een synchrone Invoke weergavecomponent:

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

Het Razor-bestand van het weergaveonderdeel:

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

Het weergaveonderdeel wordt aangeroepen in een Razor bestand (bijvoorbeeld Views/Home/Index.cshtml) met behulp van een van de volgende methoden:

Als u de IViewComponentHelper benadering wilt gebruiken, roept u het volgende aan Component.InvokeAsync:

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

Als u de Tag Helper wilt gebruiken, registreert u de assembly met het weergaveonderdeel met behulp van de @addTagHelper instructie (het weergaveonderdeel bevindt zich in een assembly genaamd MyWebApp):

@addTagHelper *, MyWebApp

Gebruik de Tag Helper voor weergaveonderdelen in het Razor markeringsbestand:

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

De methodehandtekening PriorityList.Invoke is synchroon, maar Razor zoekt en roept de methode aan met Component.InvokeAsync in het opmaakbestand.

Aanvullende bronnen

Onderdelen weergeven

Weergaveonderdelen zijn vergelijkbaar met gedeeltelijke weergaven, maar ze zijn veel krachtiger. Onderdelen weergeven maken geen gebruik van modelbinding, ze zijn afhankelijk van de gegevens die worden doorgegeven bij het aanroepen van het weergaveonderdeel. Dit artikel is geschreven met behulp van controllers en Views, maar viewcomponenten werken met Razor Pagina's.

Een weergaveonderdeel:

  • Geeft een segment weer in plaats van een geheel antwoord.
  • Bevat dezelfde scheiding van verantwoordelijkheden en testbaarheidsvoordelen tussen een controller en view.
  • Kan parameters en bedrijfslogica hebben.
  • Wordt meestal aangeroepen vanaf een indelingspagina.

Weergaveonderdelen zijn bedoeld voor herbruikbare renderinglogica die te complex is voor een gedeeltelijke weergave, zoals:

  • Dynamische navigatiemenu's
  • Tag cloud, waar query's worden uitgevoerd op de database
  • Aanmeldingsvenster
  • Winkelwagen
  • Onlangs gepubliceerde artikelen
  • Sidebar-inhoud op een blog
  • Een aanmeldingsvenster dat op elke pagina wordt weergegeven en de koppelingen voor afmelden of aanmelden weergeven, afhankelijk van de aanmeldingsstatus van de gebruiker

Een weergaveonderdeel bestaat uit twee delen:

  • De klasse, meestal afgeleid van ViewComponent
  • Het resultaat dat wordt geretourneerd, meestal een weergave.

Net als controllers kan een weergaveonderdeel een POCO zijn, maar de meeste ontwikkelaars profiteren van de methoden en eigenschappen die beschikbaar zijn door af te leiden van ViewComponent.

Wanneer u overweegt om onderdelen weer te geven die voldoen aan de specificaties van een app, kunt u in plaats daarvan onderdelen gebruiken Razor . Razor onderdelen combineren ook markeringen met C#-code om herbruikbare UI-eenheden te produceren. Razor onderdelen zijn ontworpen voor productiviteit van ontwikkelaars bij het leveren van gebruikersinterfacelogica en -samenstelling aan de clientzijde. Zie ASP.NET Core Razor-onderdelenvoor meer informatie. Zie RazorRazor Pages-app.Razor

Een weergaveonderdeel maken

Deze sectie bevat de algemene vereisten voor het maken van een weergaveonderdeel. Later in het artikel zullen we elke stap in detail onderzoeken en een weergavecomponent maken.

De weergaveonderdeelklasse

Een weergaveonderdeelklasse kan op een van de volgende manieren worden gemaakt:

  • Afgeleid van ViewComponent
  • Een klasse decoreren met het [ViewComponent] kenmerk of afgeleid van een klasse met het [ViewComponent] kenmerk
  • Een klasse maken waarin de naam eindigt met het achtervoegsel ViewComponent

Net als controllers moeten weergaveonderdelen openbare, niet-geneste en niet-abstracte klassen zijn. De naam van het weergaveonderdeel is de klassenaam waarbij het ViewComponent achtervoegsel is verwijderd. Het kan ook expliciet worden opgegeven met behulp van de Name eigenschap.

Een weergaveonderdeelklasse:

Als u wilt voorkomen dat een klasse met een niet-hoofdlettergevoelig ViewComponent achtervoegsel wordt behandeld als een weergaveonderdeel, moet u de klasse voorzien van het [NonViewComponent] kenmerk:

using Microsoft.AspNetCore.Mvc;

[NonViewComponent]
public class ReviewComponent
{
    public string Status(string name) => JobStatus.GetCurrentStatus(name);
}

Onderdeelmethoden weergeven

Een weergaveonderdeel definieert de logica in een:

  • InvokeAsync methode die retourneert Task<IViewComponentResult>.
  • Invoke een methode die synchroon een IViewComponentResult retourneert.

Parameters zijn rechtstreeks afkomstig van aanroep van het weergaveonderdeel, niet van modelbinding. Een weergaveonderdeel verwerkt nooit rechtstreeks een aanvraag. Normaal gesproken initialiseert een weergaveonderdeel een model en geeft dit door aan een weergave door de View methode aan te roepen. Kortom, bekijk de methoden voor componenten.

  • Definieer een InvokeAsync methode die een Task<IViewComponentResult> of een synchrone Invoke methode retourneert die een IViewComponentResult.
  • Initialiseert een model doorgaans en geeft het door aan een weergave door de methode ViewComponent.View aan te roepen.
  • Parameters zijn afkomstig van de aanroepmethode, niet van HTTP. Er is geen modelbinding.
  • Zijn niet rechtstreeks bereikbaar als een HTTP-eindpunt. Ze worden meestal aangeroepen in een weergave. Een weergaveonderdeel verwerkt nooit een aanvraag.
  • Worden overbelast op de handtekening in plaats van details van de huidige HTTP-aanvraag.

Zoekpad weergeven

De runtime zoekt naar de weergave in de volgende paden:

  • /Views/{Controller Name}/Components/{View Component Name}/{View Name}
  • /Views/Shared/Components/{View Component Name}/{View Name}
  • /Pages/Shared/Components/{View Component Name}/{View Name}
  • /Areas/{Area Name}/Views/Shared/Components/{View Component Name}/{View Name}

Het zoekpad is van toepassing op projecten die controllers, weergaven en Razor pagina's gebruiken.

De standaardweergavenaam voor een weergaveonderdeel is Default, wat betekent dat weergavebestanden doorgaans de naam Default.cshtmlhebben. Er kan een andere weergavenaam worden opgegeven bij het maken van het resultaat van het weergaveonderdeel of bij het aanroepen van de View methode.

U wordt aangeraden het weergavebestand Default.cshtml een naam te geven en het pad Views/Shared/Components/{View Component Name}/{View Name} te gebruiken. Het PriorityList weergavecomponent dat in dit voorbeeld wordt gebruikt, gebruikt Views/Shared/Components/PriorityList/Default.cshtml voor de weergavecomponentweergave.

Het zoekpad voor weergave aanpassen

Wijzig de Razor-verzameling van ViewLocationFormats om het zoekpad te personaliseren. Als u bijvoorbeeld wilt zoeken naar weergaven binnen het pad /Components/{View Component Name}/{View Name}, voegt u een nieuw item toe aan de verzameling:

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.

In de voorgaande code vertegenwoordigt de tijdelijke aanduiding {0} het pad Components/{View Component Name}/{View Name}.

Een weergaveonderdeel aanroepen

Als u het weergaveonderdeel wilt gebruiken, roept u het volgende aan in een weergave:

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

De parameters worden doorgegeven aan de InvokeAsync methode. Het PriorityList weergaveonderdeel dat in het artikel is ontwikkeld, wordt aangeroepen vanuit het Views/ToDo/Index.cshtml weergavebestand. In de volgende code wordt de InvokeAsync methode aangeroepen met twee parameters:

</table>

<div>
    Maximum Priority: @ViewData["maxPriority"] <br />
    Is Complete:  @ViewData["isDone"]
    @await Component.InvokeAsync("PriorityList",
                     new { 
                         maxPriority =  ViewData["maxPriority"],
                         isDone = ViewData["isDone"]  }
                     )
</div>

Een weergavecomponent aanroepen als Tag Helper

Een weergaveonderdeel kan worden aangeroepen als een Tag Helper:

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

Pascal-cased klasse- en methodeparameters voor Tag Helpers worden omgezet in hun kebab case. De Tag Helper voor het aanroepen van een weergaveonderdeel maakt gebruik van het <vc></vc> element. Het weergaveonderdeel wordt als volgt opgegeven:

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

Als u een weergaveonderdeel wilt gebruiken als Tag Helper, registreert u de assembly met het weergaveonderdeel met behulp van de @addTagHelper instructie. Als het weergaveonderdeel zich in een assembly bevindt met de naam MyWebApp, voegt u de volgende instructie toe aan het _ViewImports.cshtml bestand:

@addTagHelper *, MyWebApp

Een weergaveonderdeel kan worden geregistreerd als Tag Helper voor elk bestand dat verwijst naar het weergaveonderdeel. Zie Tag Helper-bereik beheren voor meer informatie over het registreren van Tag Helpers.

De InvokeAsync methode die in deze handleiding wordt gebruikt:

@await Component.InvokeAsync("PriorityList",
                 new { 
                     maxPriority =  ViewData["maxPriority"],
                     isDone = ViewData["isDone"]  }
                 )

In de voorgaande markeringen wordt de PriorityList-weergavecomponent priority-list. De parameters voor het weergavecomponent worden doorgegeven als attributen in kebab-case.

Een weergaveonderdeel rechtstreeks vanuit een controller aanroepen

Weergaveonderdelen worden doorgaans aangeroepen vanuit een weergave, maar ze kunnen rechtstreeks vanuit een controllermethode worden aangeroepen. Hoewel weergaveonderdelen geen eindpunten zoals controllers definiëren, kan een controlleractie die de inhoud van een bestand ViewComponentResult retourneert, worden geïmplementeerd.

In het volgende voorbeeld wordt het weergaveonderdeel rechtstreeks vanuit de controller aangeroepen:

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

Een basisweergaveonderdeel maken

Download, bouw en test de starterscode. Het is een basisproject met een ToDo controller waarmee een lijst met taken wordt weergegeven.

Lijst met ToDos

De controller bijwerken om de prioriteit en voltooiingsstatus door te geven

Werk de methode bij voor het Index gebruik van parameters voor prioriteits- en voltooiingsstatus:

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

Een ViewComponent-klasse toevoegen

Voeg een ViewComponent-klasse toe aan 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();
    }
}

Opmerkingen over de code:

  • Weergavecomponentklassen kunnen zich in elke map in het project bevinden.

  • Omdat de klassenaam PriorityListViewComponent eindigt met het achtervoegsel ViewComponent, gebruikt de runtime de tekenreeks PriorityList bij het verwijzen naar het klasseonderdeel vanuit een weergave.

  • Het [ViewComponent] kenmerk kan de naam wijzigen die wordt gebruikt om te verwijzen naar een weergaveonderdeel. De klasse had bijvoorbeeld kunnen zijn genoemd XYZ met het volgende [ViewComponent] attribuut:

    [ViewComponent(Name = "PriorityList")]
       public class XYZ : ViewComponent
    
  • Het [ViewComponent] kenmerk in de voorgaande code geeft aan dat de viewcomponentselector gebruikt moet worden:

    • De naam PriorityList bij het zoeken naar de weergaven die aan de component zijn gekoppeld
    • De tekenreeks PriorityList bij het verwijzen naar het klasseonderdeel vanuit een weergave.
  • Het onderdeel maakt gebruik van afhankelijkheidsinjectie om de gegevenscontext beschikbaar te maken.

  • InvokeAsync maakt een methode beschikbaar die vanuit een weergave kan worden aangeroepen en kan een willekeurig aantal argumenten duren.

  • De InvokeAsync methode retourneert de set ToDo items die voldoen aan de isDone en maxPriority parameters.

Maak de weergavecomponent Razor

  • Maak de map Views/Shared/Components . Deze map moet de naam Components hebben.

  • Maak de map Views/Shared/Components/PriorityList . Deze mapnaam moet overeenkomen met de naam van de weergaveonderdeelklasse of de naam van de klasse minus het achtervoegsel. Als het ViewComponent kenmerk wordt gebruikt, moet de klassenaam overeenkomen met de kenmerkaanduiding.

  • Views/Shared/Components/PriorityList/Default.cshtml Razor Een weergave maken:

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

    De Razor weergave neemt een lijst van TodoItem en geeft deze weer. Als de weergaveonderdeelmethode InvokeAsync de naam van de weergave niet doorgeeft, wordt standaard gebruikt voor de weergavenaam op conventie. Als u de standaardstijl voor een specifieke controller wilt overschrijven, voegt u een weergave toe aan de controllerspecifieke weergavemap (bijvoorbeeld Weergaven/ToDo/Components/PriorityList/Default.cshtml).

    Als het weergaveonderdeel controllerspecifiek is, kan het worden toegevoegd aan de controllerspecifieke map. Is bijvoorbeeld Views/ToDo/Components/PriorityList/Default.cshtml controllerspecifiek.

  • Voeg een div bestand met een aanroep toe aan het onderdeel prioriteitslijst onderaan het Views/ToDo/index.cshtml bestand:

    </table>
    
    <div>
        Maximum Priority: @ViewData["maxPriority"] <br />
        Is Complete:  @ViewData["isDone"]
        @await Component.InvokeAsync("PriorityList",
                         new { 
                             maxPriority =  ViewData["maxPriority"],
                             isDone = ViewData["isDone"]  }
                         )
    </div>
    

De markering @await Component.InvokeAsync toont de syntaxis voor het aanroepen van weergaveonderdelen. Het eerste argument is de naam van het onderdeel dat we willen aanroepen of oproepen. Volgende parameters worden doorgegeven aan het onderdeel. InvokeAsync kan een willekeurig aantal argumenten aannemen.

De app testen. In de volgende afbeelding ziet u de takenlijst en de prioriteitsitems:

takenlijst en prioriteitsitems

Het weergaveonderdeel kan rechtstreeks vanuit de controller worden aangeroepen:

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

prioriteitsitems uit de indexVC-actie

Geef een weergaveonderdeelnaam op

Een onderdeel voor een complexe weergave moet mogelijk een niet-standaardweergave opgeven onder bepaalde omstandigheden. De volgende code laat zien hoe u de 'PVC'-weergave opgeeft vanuit de InvokeAsync methode. Werk de InvokeAsync methode in de PriorityListViewComponent klasse bij.

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

Kopieer het Views/Shared/Components/PriorityList/Default.cshtml bestand naar een weergave met de naam Views/Shared/Components/PriorityList/PVC.cshtml. Voeg een kop toe om aan te geven dat de PVC-weergave wordt gebruikt.

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

Voer de app uit en controleer de PVC-weergave.

Onderdeel Prioriteitsweergave

Als de PVC-weergave niet wordt weergegeven, controleert u of het weergaveonderdeel met een prioriteit van 4 of hoger wordt aangeroepen.

Het weergavepad onderzoeken

  • Wijzig de prioriteitsparameter in drie of minder, zodat de prioriteitsweergave niet wordt geretourneerd.

  • Wijzig de naam van het Views/ToDo/Components/PriorityList/Default.cshtml item tijdelijk in 1Default.cshtml.

  • Test de app, de volgende fout treedt op:

    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
    
  • Kopieer Views/ToDo/Components/PriorityList/1Default.cshtml naar Views/Shared/Components/PriorityList/Default.cshtml.

  • Voeg een aantal markeringen toe aan de Gedeelde takenlijst onderdeelweergave om aan te geven dat de weergave afkomstig is uit de Gedeelde map.

  • Test de weergave Gedeeld onderdeel .

ToDo-uitvoer met de weergave Gedeeld onderdeel

Vermijd vastgelegde tekenreeksen

Vervang de naam van het in code vastgelegde weergaveonderdeel door de klassenaam voor de veiligheid van de compilatietijd. Werk het PriorityListViewComponent.cs-bestand bij om het achtervoegsel ViewComponent niet te gebruiken:

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

Het weergavebestand:

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

Een overbelasting van de Component.InvokeAsync methode die een CLR-type gebruikt, maakt gebruik van de typeof operator:

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

Synchroon werk uitvoeren

Het framework verwerkt het aanroepen van een synchrone Invoke methode als asynchroon werk niet vereist is. Met de volgende methode maakt u een synchrone Invoke weergavecomponent:

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

Het Razor-bestand van het weergaveonderdeel:

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

Het weergaveonderdeel wordt aangeroepen in een Razor bestand (bijvoorbeeld Views/Home/Index.cshtml) met behulp van een van de volgende methoden:

Als u de IViewComponentHelper benadering wilt gebruiken, roept u het volgende aan Component.InvokeAsync:

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

Als u de Tag Helper wilt gebruiken, registreert u de assembly met het weergaveonderdeel met behulp van de @addTagHelper instructie (het weergaveonderdeel bevindt zich in een assembly genaamd MyWebApp):

@addTagHelper *, MyWebApp

Gebruik de Tag Helper voor weergaveonderdelen in het Razor markeringsbestand:

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

De methodehandtekening PriorityList.Invoke is synchroon, maar Razor zoekt en roept de methode aan met Component.InvokeAsync in het opmaakbestand.

Aanvullende bronnen

Voorbeeldcode bekijken of downloaden (hoe download je)

Onderdelen weergeven

Weergaveonderdelen zijn vergelijkbaar met gedeeltelijke weergaven, maar ze zijn veel krachtiger. Viewcomponenten maken geen gebruik van modelbinding en zijn alleen afhankelijk van de gegevens die worden verstrekt bij de aanroep. Dit artikel is geschreven met behulp van controllers en views, maar weergaveonderdelen werken ook met Razor pagina's.

Een weergaveonderdeel:

  • Geeft een segment weer in plaats van een geheel antwoord.
  • Bevat dezelfde scheiding van verantwoordelijkheden en testbaarheidsvoordelen tussen een controller en view.
  • Kan parameters en bedrijfslogica hebben.
  • Wordt meestal aangeroepen vanaf een indelingspagina.

Weergaveonderdelen zijn bedoeld overal waar u herbruikbare renderinglogica hebt die te complex is voor een gedeeltelijke weergave, zoals:

  • Dynamische navigatiemenu's
  • Tagcloud (waar query's worden uitgevoerd op de database)
  • Aanmeldingsvenster
  • Winkelwagen
  • Onlangs gepubliceerde artikelen
  • Sidebar-inhoud op een typische blog
  • Een aanmeldingsvenster dat op elke pagina wordt weergegeven en de koppelingen naar afmelden of aanmelden weergeven, afhankelijk van de aanmeldingsstatus van de gebruiker

Een weergaveonderdeel bestaat uit twee delen: de klasse (meestal afgeleid van ViewComponent) en het resultaat dat wordt geretourneerd (meestal een weergave). Net als controllers kan een weergaveonderdeel een POCO zijn, maar de meeste ontwikkelaars profiteren van de methoden en eigenschappen die beschikbaar zijn door af te leiden van ViewComponent.

Wanneer u overweegt om onderdelen weer te geven die voldoen aan de specificaties van een app, kunt u in plaats daarvan onderdelen gebruiken Razor . Razor onderdelen combineren ook markeringen met C#-code om herbruikbare UI-eenheden te produceren. Razor onderdelen zijn ontworpen voor productiviteit van ontwikkelaars bij het leveren van gebruikersinterfacelogica en -samenstelling aan de clientzijde. Zie ASP.NET Core Razor-onderdelenvoor meer informatie. Zie RazorRazor Pages-app.Razor

Een weergaveonderdeel maken

Deze sectie bevat de algemene vereisten voor het maken van een weergaveonderdeel. Later in het artikel zullen we elke stap in detail onderzoeken en een weergavecomponent maken.

De weergaveonderdeelklasse

Een weergaveonderdeelklasse kan op een van de volgende manieren worden gemaakt:

  • Afgeleid van ViewComponent
  • Een klasse decoreren met het [ViewComponent] kenmerk of afgeleid van een klasse met het [ViewComponent] kenmerk
  • Een klasse maken waarin de naam eindigt met het achtervoegsel ViewComponent

Net als controllers moeten weergaveonderdelen openbare, niet-geneste en niet-abstracte klassen zijn. De naam van het weergaveonderdeel is de klassenaam waarbij het achtervoegsel ViewComponent is verwijderd. Het kan ook expliciet worden opgegeven met behulp van de ViewComponentAttribute.Name eigenschap.

Een weergaveonderdeelklasse:

Als u wilt voorkomen dat een klasse met een niet-hoofdlettergevoelig ViewComponent-achtervoegsel wordt behandeld als een weergaveonderdeel, versiert u de klasse met het kenmerk [NonViewComponent] :

[NonViewComponent]
public class ReviewComponent
{
    // ...

Onderdeelmethoden weergeven

Een weergaveonderdeel definieert de logica in een InvokeAsync methode die een Task<IViewComponentResult> of in een synchrone Invoke methode retourneert die een IViewComponentResult. Parameters zijn rechtstreeks afkomstig van aanroep van het weergaveonderdeel, niet van modelbinding. Een weergaveonderdeel verwerkt nooit rechtstreeks een aanvraag. Normaal gesproken initialiseert een weergaveonderdeel een model en geeft dit door aan een weergave door de View methode aan te roepen. Kortom, bekijk de methoden voor componenten.

  • Definieer een InvokeAsync methode die een Task<IViewComponentResult> of een synchrone Invoke methode retourneert die een IViewComponentResult.
  • Initialiseert een model doorgaans en geeft dit door aan een weergave door de ViewComponentView methode aan te roepen.
  • Parameters zijn afkomstig van de aanroepmethode, niet van HTTP. Er is geen modelbinding.
  • Zijn niet rechtstreeks bereikbaar als een HTTP-eindpunt. Ze worden aangeroepen vanuit uw code (meestal in een view). Een weergaveonderdeel verwerkt nooit een aanvraag.
  • Worden overbelast op de handtekening in plaats van details van de huidige HTTP-aanvraag.

Zoekpad weergeven

De runtime zoekt naar de weergave in de volgende paden:

  • /Views/{Controller Name}/Components/{View Component Name}/{View Name}
  • /Views/Shared/Components/{View Component Name}/{View Name}
  • /Pages/Shared/Components/{View Component Name}/{View Name}
  • /Areas/{Area Name}/Views/Shared/Components/{View Component Name}/{View Name}

Het zoekpad is van toepassing op projecten die controllers, weergaven en Razor pagina's gebruiken.

De standaardweergavenaam voor een weergaveonderdeel is Standaard, wat betekent dat uw weergavebestand meestal de naam krijgt Default.cshtml. U kunt een andere weergavenaam opgeven bij het maken van het resultaat van het weergaveonderdeel of bij het aanroepen van de View methode.

U wordt aangeraden het weergavebestand Default.cshtml een naam te geven en het pad Views/Shared/Components/{View Component Name}/{View Name} te gebruiken. Het PriorityList weergavecomponent dat in dit voorbeeld wordt gebruikt, gebruikt Views/Shared/Components/PriorityList/Default.cshtml voor de weergavecomponentweergave.

Het zoekpad voor weergave aanpassen

Wijzig de Razor-verzameling van ViewLocationFormats om het zoekpad te personaliseren. Als u bijvoorbeeld wilt zoeken naar weergaven in het pad '/Components/{View Component Name}/{View Name}', voegt u een nieuw item toe aan de verzameling:

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

In de voorgaande code vertegenwoordigt de tijdelijke aanduiding '{0}' het pad 'Components/{View Component Name}/{View Name}'.

Een weergaveonderdeel aanroepen

Als u het weergaveonderdeel wilt gebruiken, roept u het volgende aan in een weergave:

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

De parameters worden doorgegeven aan de InvokeAsync methode. Het PriorityList weergaveonderdeel dat in het artikel is ontwikkeld, wordt aangeroepen vanuit het Views/ToDo/Index.cshtml weergavebestand. In het volgende wordt de InvokeAsync methode aangeroepen met twee parameters:

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

Een weergaveonderdeel aanroepen als Tag-Helper

Voor ASP.NET Core 1.1 en hoger kunt u een weergaveonderdeel aanroepen als Tag Helper:

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

Pascal-cased klasse- en methodeparameters voor Tag Helpers worden omgezet in hun kebab case. De Tag Helper voor het aanroepen van een weergaveonderdeel maakt gebruik van het <vc></vc> element. Het weergaveonderdeel wordt als volgt opgegeven:

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

Als u een weergaveonderdeel wilt gebruiken als Tag Helper, registreert u de assembly met het weergaveonderdeel met behulp van de @addTagHelper instructie. Als uw weergaveonderdeel zich in een assembly bevindt met de naam MyWebApp, voegt u de volgende instructie toe aan het _ViewImports.cshtml bestand:

@addTagHelper *, MyWebApp

U kunt een weergaveonderdeel registreren als Tag Helper voor elk bestand dat verwijst naar het weergaveonderdeel. Zie Tag Helper-bereik beheren voor meer informatie over het registreren van Tag Helpers.

De InvokeAsync methode die in deze handleiding wordt gebruikt:

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

In Tag Helper-markup:

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

In het bovenstaande voorbeeld wordt het weergaveonderdeel PriorityListpriority-list. De parameters voor het weergavecomponent worden doorgegeven als attributen in kebab-case.

Een weergaveonderdeel rechtstreeks vanuit een controller aanroepen

Weergaveonderdelen worden doorgaans aangeroepen vanuit een weergave, maar u kunt ze rechtstreeks vanuit een controllermethode aanroepen. Hoewel de weergaveonderdelen geen eindpunten zoals controllers definiëren, kunt u eenvoudig een controlleractie implementeren die de inhoud van een ViewComponentResult.

In dit voorbeeld wordt het weergaveonderdeel rechtstreeks aangeroepen vanaf de controller:

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

Overzicht: Een eenvoudig weergaveonderdeel maken

Download, bouw en test de starterscode. Het is een eenvoudig project met een ToDo controller die een ToDo-lijst weergeeft.

Lijst met ToDos

Een ViewComponent-klasse toevoegen

Maak een ViewComponents-map en voeg de volgende PriorityListViewComponent klasse toe:

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

Opmerkingen over de code:

  • Weergavecomponentklassen kunnen zich in elke map in het project bevinden.

  • Omdat de klassenaam PriorityListViewComponent eindigt met het achtervoegsel ViewComponent, gebruikt de runtime de tekenreeks PriorityList bij het verwijzen naar het klasseonderdeel vanuit een weergave.

  • Het [ViewComponent] kenmerk kan de naam wijzigen die wordt gebruikt om te verwijzen naar een weergaveonderdeel. De klasse kan bijvoorbeeld zijn benoemd XYZ met het ViewComponent kenmerk:

    [ViewComponent(Name = "PriorityList")]
       public class XYZ : ViewComponent
    
  • Het [ViewComponent] kenmerk in de voorgaande code geeft aan dat de viewcomponentselector gebruikt moet worden:

    • De naam PriorityList bij het zoeken naar de weergaven die aan de component zijn gekoppeld
    • De tekenreeks PriorityList bij het verwijzen naar het klasseonderdeel vanuit een weergave.
  • Het onderdeel maakt gebruik van afhankelijkheidsinjectie om de gegevenscontext beschikbaar te maken.

  • InvokeAsync maakt een methode beschikbaar die vanuit een weergave kan worden aangeroepen en kan een willekeurig aantal argumenten duren.

  • De InvokeAsync methode retourneert de set ToDo items die voldoen aan de isDone en maxPriority parameters.

Maak de weergavecomponent Razor

  • Maak de map Views/Shared/Components . Deze map moet de naam Componentshebben.

  • Maak de map Views/Shared/Components/PriorityList . Deze mapnaam moet overeenkomen met de naam van de weergaveonderdeelklasse of de naam van de klasse min het achtervoegsel (als we de conventie hebben gevolgd en het ViewComponent-achtervoegsel in de klassenaam hebben gebruikt). Als u het ViewComponent kenmerk hebt gebruikt, moet de klassenaam overeenkomen met de kenmerkaanduiding.

  • Views/Shared/Components/PriorityList/Default.cshtml Razor Een weergave maken:

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

    De Razor weergave neemt een lijst van TodoItem en geeft deze weer. Als de methode voor het weergaveonderdeel InvokeAsync niet de naam van de weergave doorgeeft (zoals in ons voorbeeld), wordt standaard gebruikt voor de weergavenaam volgens conventie. Verderop in de handleiding laat ik zien hoe je de naam van de weergave doorgeeft. Als u de standaardstijl voor een specifieke controller wilt overschrijven, voegt u een weergave toe aan de controllerspecifieke weergavemap (bijvoorbeeld Weergaven/ToDo/Components/PriorityList/Default.cshtml).

    Als het weergaveonderdeel controllerspecifiek is, kunt u het toevoegen aan de controllerspecifieke map (Views/ToDo/Components/PriorityList/Default.cshtml).

  • Voeg een div bestand met een aanroep toe aan het onderdeel prioriteitslijst onderaan het Views/ToDo/index.cshtml bestand:

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

De markering @await Component.InvokeAsync toont de syntaxis voor het aanroepen van weergaveonderdelen. Het eerste argument is de naam van het onderdeel dat we willen aanroepen of oproepen. Volgende parameters worden doorgegeven aan het onderdeel. InvokeAsync kan een willekeurig aantal argumenten aannemen.

De app testen. In de volgende afbeelding ziet u de takenlijst en de prioriteitsitems:

takenlijst en prioriteitsitems

U kunt het weergaveonderdeel ook rechtstreeks vanuit de controller aanroepen:

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

prioriteitsitems uit de indexVC-actie

Een weergavenaam opgeven

Een onderdeel voor een complexe weergave moet mogelijk een niet-standaardweergave opgeven onder bepaalde omstandigheden. De volgende code laat zien hoe u de 'PVC'-weergave opgeeft vanuit de InvokeAsync methode. Werk de InvokeAsync methode in de PriorityListViewComponent klasse bij.

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

Kopieer het Views/Shared/Components/PriorityList/Default.cshtml bestand naar een weergave met de naam Views/Shared/Components/PriorityList/PVC.cshtml. Voeg een kop toe om aan te geven dat de PVC-weergave wordt gebruikt.

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

Views/ToDo/Index.cshtmlbijwerken:

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

Voer de app uit en controleer de PVC-weergave.

Onderdeel Prioriteitsweergave

Als de PVC-weergave niet wordt weergegeven, controleert u of u het weergaveonderdeel aanroept met een prioriteit van 4 of hoger.

Het weergavepad onderzoeken

  • Wijzig de prioriteitsparameter in drie of minder, zodat de prioriteitsweergave niet wordt geretourneerd.

  • Wijzig de naam van het Views/ToDo/Components/PriorityList/Default.cshtml item tijdelijk in 1Default.cshtml.

  • Test de app en u krijgt de volgende fout:

    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
    
  • Kopieer Views/ToDo/Components/PriorityList/1Default.cshtml naar Views/Shared/Components/PriorityList/Default.cshtml.

  • Voeg een aantal markeringen toe aan de Gedeelde takenlijst onderdeelweergave om aan te geven dat de weergave afkomstig is uit de Gedeelde map.

  • Test de weergave Gedeeld onderdeel .

ToDo-uitvoer met de weergave Gedeeld onderdeel

In code vastgelegde tekenreeksen vermijden

Als u tijdveiligheid wilt compileren, kunt u de naam van het in code vastgelegde weergaveonderdeel vervangen door de klassenaam. Maak het weergaveonderdeel zonder het achtervoegsel 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();
        }
    }
}

Voeg een using instructie toe aan uw Razor weergavebestand en gebruik de nameof operator:

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

U kunt een overload van de Component.InvokeAsync-methode gebruiken die een CLR-type accepteert. Vergeet niet om in dit geval de typeof operator te gebruiken:

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

Synchroon werk uitvoeren

Het framework verwerkt het aanroepen van een synchrone Invoke methode als u geen asynchroon werk hoeft uit te voeren. Met de volgende methode maakt u een synchrone Invoke weergavecomponent:

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

Het bestand van Razor het weergaveonderdeel bevat de tekenreeksen die aan de Invoke methode zijn doorgegeven (Views/Home/Components/PriorityList/Default.cshtml):

@model List<string>

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

Het weergaveonderdeel wordt aangeroepen in een Razor bestand (bijvoorbeeld Views/Home/Index.cshtml) met behulp van een van de volgende methoden:

Als u de IViewComponentHelper benadering wilt gebruiken, roept u het volgende aan Component.InvokeAsync:

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

Als u de Tag Helper wilt gebruiken, registreert u de assembly met het weergaveonderdeel met behulp van de @addTagHelper instructie (het weergaveonderdeel bevindt zich in een assembly genaamd MyWebApp):

@addTagHelper *, MyWebApp

Gebruik de Tag Helper voor weergaveonderdelen in het Razor markeringsbestand:

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

De methodehandtekening PriorityList.Invoke is synchroon, maar Razor zoekt en roept de methode aan met Component.InvokeAsync in het opmaakbestand.

Alle parameters voor weergaveonderdelen zijn vereist

Elke parameter in een weergaveonderdeel is een vereist kenmerk. Bekijk dit GitHub-probleem. Als er een parameter wordt weggelaten:

  • De handtekening van de InvokeAsync methode komt niet overeen, daarom wordt de methode niet uitgevoerd.
  • De ViewComponent geeft geen markeringen weer.
  • Er zullen geen fouten optreden.

Aanvullende bronnen