Mehr von Jürgen Gutsch

Mehr von Jürgen Gutsch

Empfehlungen von Jürgen Gutsch

Blog-Empfehlungen von Jürgen Gutsch

Willkommen bei ASP.NET Zone. Anmelden | Registrieren | Hilfe

Jürgen Gutsch

ASP.NET und mehr...
View Components in ASP.NET 5

Eine der schönsten Neuerungen in ASP.NET 5 sind die View Commponents. Diese sind eine Art Mini MVC innerhalb der MVC Applikation die sich allerdings einbinden lassen wie PartialViews. Also Partielle Views mit eigenem Controller. In etwa Vergleichbar mit User Controls in ASP.NET Webforms. Anwendungsfälle wären wiederkehrende Elemente einer Website oder eins Blogs, die nichts direkt mit dem eigentlichen Inhalt zu tun haben. Also alles was nicht unbedingt über die aktuelle Controller Action kommen muss. Nehmen wir als Beispiel das Blog, das außer die Artikelliste und den Artikel noch mehr enthält, wie z. B: eine Navigation, Tag-Liste, Linkliste, Archivübersicht, etc. Das alles kann man über die aktuelle Controller Action ermitteln und an die View geben. Allerdings muss das in jeder View immer wieder gemacht werden.

Schöner wäre es, wenn sich die aktuellen Actions nur mit dem befassen was ihre primäre Aufgabe ist: Das ermitteln und zurückgeben eines Artikels, oder das ermitteln und zurückgeben einer Artikelliste. Alle anderen genannten Teile des Blogs könnten doch irgendwo anders passieren, wo es die Actions nicht mit Logik zumüllt für die die Actions nicht zuständig sein sollten.

Genau hier kommen die View Components ins Spiel:

Zuerst wird eine Klasse erstellt, die von ViewComponent ableitet und ViewComponent als Sufix haben sollte, z. B. TopTagsViewComponent:

public class TopTagsViewComponent : ViewComponent
{
    private readonly ITagService _tagService;

    public TopTagsViewComponent(ITagService tagService)
    {
        _tagService = tagService;
    }

    public IViewComponentResult Invoke()
    {
         var tags = _tagService.LoadTopTags();
         var models = tags.Select(=>
            new TagViewModel
            {
                Id = tag.Id,
                Name = tag.Name
            });
        return View(models);
    }
}

Die Methode Invoke entspricht der Action in einem regulären Controller, an deren Ende eine View erzeugt und zurückgegeben wird. Der TagService der hier genutzt wird kann per IoC in die ViewComponent hineingegeben werden. Da IoC wirklich überall zur Verfügung steht, kann auf jede Quelle zugegriffen werden, auf die eine regulärer Controller zugreift.

Die View ist eine ganz normale Razor View:

@model IEnumerable<WebApp1.ViewComponents.TagViewModel>

@if (Model.Any())
{
    <ul>
        @foreach (var tag in Tags)
        {
            <li>
                [@tag.Id] @tag.Name
            </li>
        }
    </ul>
}

Einzig der Ort an dem diese View abgelegt werden muss ist ein wenig speziell. Die Views werden unter Shared in einem Ordner Components abgelegt. Dort wiederum in einem Unterordner, der dem Namen der ViewComponent ohne dessen Sufix entspricht. Unsere ViewComponent View liegt also unter /Shared/Components/TopTags/Default.cshtml

Der Standardname ist Default.cshtml. Es kann aber auch jeder beliebige andere Name verwendet werden, wenn dieser in der Methode Invoke angegeben wird:

return View("TheNicerName", models);

Auf die Art könnte man auch innerhalb der ViewComponent daas Template wechseln, wenn es erforderlich sein sollte.

Die oben beschriebene Komponente wird dann ganz einfach, fast ähnlich wie eine PartialView eingebunden:

@Component.Invoke("TopTags");

Argumente übergeben

Interessant werden ViewComponents auch, wenn man Argumente übergibt. Angenommen wir möchten die Zahl der Tags anpassen, je nachdem, wo wir die Liste einsetzen wollen.

Wir erweitern die Methode Invoke einfach um ein Argument:

public IViewComponentResult Invoke(int count)     

    var tags = _tagService.LoadTopTags().Take(count);     
    var models = tags.Select(tag =>
        new TagViewModel 
        { 
            Id = tag.Id, 
            Name = tag.Name 
        }); 
     return View(models); 
}

Und rufen die Methode Invoke auch einfach mit diesem zusätzlichen Argument auf:

@Component.Invoke("TopTags", 10);

Asynchrone ViewComponents

Um Asynchrone Views besser zu unterstützen, kann statt der synchronen Methode Invoke auch eine asynchrone Methode geschrieben werden:

public async Task<IViewComponentResult> InvokeAsync(int count)     

    var tags = await _tagService.LoadTopTags();     
    var models = tags.Select(=>
        new TagViewModel 
        { 
            Id = tag.Id, 
            Name = tag.Name 
        }).Take(count); 
     return View(models); 
}

Bei der Nutzung muss dann await genutzt werden:

@await Component.InvokeAsync("TopTags", 10);

Posted: Mittwoch, 25. November 2015 08:16 von Jürgen Gutsch

Kommentare

thoemmi sagte:

Vielen Dank für Deine Einführung, Jürgen. Der Konstruktor von TopTagsViewComponent sollte aber nicht RecommendedProductsViewComponent heißen ;)

# November 25, 2015 18:09

thoemmi sagte:

Ah, und in @Component.Invoke("ToTags") soll das Argument wohl "TopTags"heißen

# November 25, 2015 18:10

Jürgen Gutsch sagte:

Autsch, du hast natürlich recht. Vielen Dank für den Hinweis :)

# November 25, 2015 19:53
Anonyme Kommentare sind nicht zugelassen