ASP.NET Core View Components
Home

ASP.NET Core View Components

ASP.NET Core View Components

Je kon in de vorige versies van ASP.NET MVC in een view een partial view insluiten die vooraleer geladen werd eerst langs de controller passeerde om bepaalde business logica te laten uitvoeren of om een een specifiek model aan te maken voor deze specifieke partial view. Dit kan niet meer .NET Core. In plaats daarvan moet je nu een klasse maken die overeft van een ViewComponent klasse gebruiken.

Inleiding

View componenten zijn nieuw in ASP.NET Core en zijn vergelijkbaar met partial views. Deze componenten zijn krachtiger dan partial views. Ze gebruiken echter geen model binding. Ze zijn enkel en alleen afhankelijk van de gegevens die je meegeeft wanneer je ze oproept:

Componenten zijn goede kandidaten bij refactoring, wanneer je vaststelt dat de herbruikbare rendering logica te complex is om in partial views te stoppen. Denk bijvoorbeeld aan:

Een view component bestaat uit twee delen:

  1. de klasse (gewoonlijk afgeleid van ViewComponent);
  2. het resultaat dat geretourneerd wordt, meestal een view;

Een view component maken

Een view component klasse kan je op drie verschillende manieren maken:

  1. maak een klasse die overerft van ViewComponent;
  2. decoreer een klase met het [ViewComponent] attribuut of een klasse afleiden van een klasse met een [ViewComponent] attribuut;
  3. een klasse maken waarvan de naam eindigt met het achtervoegsel ViewComponent;

De derde methode gaan wij in ons voorbeeld toepassen.

De methoden van een view component

De logica van een view component wordt gedefinieerd in een InvokeAsync methode die een IViewComponentResult retourneert. Parameters worden meegegeven wanneer de view component wordt aangeroepen, niet vanuit model binding. Een view component handelt nooit rechtstreeks een request af.

Een view component initialiseert zelf een model en geeft het door aan een view door de View-methode op te roepen.

Samengevat:

definieer een InvokeAsync methode die een IViewComponentResult retourneert;

initialiseert een model en geef het door aan een view door een ViewComponent View methode op te roepen;

parameters worden ingevuld door de argumenten die door de aanroepende methode worden meegegeven en niet door HTTP, er is geen model binding;

view components zijn niet direct te bereiken als HTTP-eindpunt, ze worden rechtstreels aangeroepen vanuit je code (meestal in de view). Een view component handelt nooit een request af;

View zoekpad

De runtime zoekt de view langs ee, de volgende twee wegen:

  1. Views/<controller_name>/Components/<view_component_name>/<VIEW_NAME>
  2. Views/Shared/Components/<view_component_name>/<VIEW_NAME>

De standaard view naam voor een component is Default, wat betekent dat een view bestand doorgaans de naam Default.cshtml zal dragen. Je kan een andere naam aan de view geven maar dan moet je die naam ook expliceit opgeven als je de view-methode aanroept.

.NET Core raadt aan het view bestand de naam Default.cshtml te geven en deze te plaatsen in de map met de naam Views/Shared/Components/<view_component_name>/<VIEW_NAME>.

In het voorbeeld hieronder heet de view Views/Shared/Components/CountryAll/Default.cshtml.

Een view component aanroepen

Om een view component aan te roepen gebruik je

@Component.InvokeAsync ("Naam van view component", <anonieme gegeventypes die parameters bevatten>)

vanuit uit een view.

De parameters worden doorgegeven aan de InvokeAsync methode. De ReadAll view component die we hieronder maken wordt opgeroepen vanuit de Views/ Country/Create.cshtml view bestand:

@await Component.InvokeAsync("CountryAll")

Een view component aanroepen vanuit de controller

Viewcomponenten worden meestal aangeroepen uit een view. Maar refactoring zou niet volledig zijn als je zo ook niet rechtstreeks vanuit een controller methode zou kunnen aanroepen. Hoewel view componenten geen HTTP-eindpunten zijn zoals controllers, kan je gemakkelijk een controller actie schrijven die de inhoud van een ViewComponentResult retourneert:

Je kan de volgende methode in de CountryController toevoegen:

public IActionResult ReadAll ()
{
     returnViewComponent ("CountryAll");
}

Stappenplan implementeren CoutryAllViewComponent

Een ViewComponent toevoegen

Maak de CountryAllViewComponent klasse in ViewComponents/CountryAllViewComponent.cs:

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

namespace Mikmak.ViewComponents
{
    public class CountryAllViewComponent : ViewComponent
    {
        private readonly MikmakDbContext _context;

        public CountryAllViewComponent(MikmakDbContext context)
        {
            _context = context;
        }

        public async Task<IViewComponentResult> InvokeAsync()
        {
            IEnumerable list = await _context.Country.ToListAsync();
            return View(list);
        }
    }
}

De view

Maak de Razor view voor de component in het bestand Views\Shared\Components\CountryAll\Default.cshtml:

@model IEnumerable<Mikmak.Models.Country>

<table class="list">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Code)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Code)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Name)
                </td>
                <td>
                    <a asp-action="Details" asp-route-id="@item.Id">Details</a>
                    <a href="/Country/Details/@item.Id">Details</a>
                </td>
            </tr>
        }
    </tbody>
</table>

De component aanroepen

De component roep je aan in de Razor view met de naam Views\Country\Create.cshtml:

@model Mikmak.Models.Country

@{
    ViewData["Title"] = "Create";
}

<h2>Create</h2>
<form method="post" action="/Country/Create">
    <div class="form-horizontal">
        <h4>Country</h4>
        <hr />
        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
        <div class="form-group">
            <label asp-for="Code" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input asp-for="Code" class="form-control" />
                <input name="Code" id="Code" type="text" class="form-control" />
                <span asp-validation-for="Code" class="text-danger" />
            </div>
        </div>
        <div class="form-group">
            <label asp-for="Latitude" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input asp-for="Latitude" class="form-control" />
                <span asp-validation-for="Latitude" class="text-danger" />
            </div>
        </div>
        <div class="form-group">
            <label asp-for="Longitude" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input asp-for="Longitude" class="form-control" />
                <span asp-validation-for="Longitude" class="text-danger" />
            </div>
        </div>
        <div class="form-group">
            <label asp-for="Name" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input asp-for="Name" class="form-control" />
                <span asp-validation-for="Name" class="text-danger" />
            </div>
        </div>
        <div class="form-group">
            <label asp-for="ShippingCostMultiplier" class="col-md-2 control-label"></label>
            <div class="col-md-10">
                <input asp-for="ShippingCostMultiplier" class="form-control" />
                <span asp-validation-for="ShippingCostMultiplier" class="text-danger" />
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
</form>
@await Component.InvokeAsync("CountryAll")
<div>
    <a asp-action="Index">Back to List</a>
</div>
@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

JI
2017-01-27 17:06:30