Dela via


Visa komponenter i ASP.NET Core

Av Rick Anderson

Visa komponenter

Visningskomponenter liknar partiella vyer, men de är mycket kraftfullare. Visa komponenter använder inte modellbindning, de är beroende av de data som skickas när du anropar vykomponenten. Den här artikeln skrevs med hjälp av kontroller och vyer, men vykomponenter fungerar med Razor Sidor.

En vykomponent:

  • Renderar ett segment i stället för ett helt svar.
  • Inkluderar samma fördelar med ansvarsseparation och testbarhet som finns mellan en controller och en vy.
  • Kan ha parametrar och affärslogik.
  • Anropas vanligtvis från en layoutsida.

Vykomponenter är avsedda för situationer med återanvändbar renderingslogik som är för komplex för en partiell vy, till exempel:

  • Dynamiska navigeringsmenyer
  • Taggmoln, där det gör en sökning i databasen
  • Inloggningspanel
  • Kundvagn
  • Nyligen publicerade artiklar
  • Sidofältsinnehåll på en blogg
  • En inloggningspanel som återges på varje sida och visar antingen länkarna för att logga ut eller logga in, beroende på användarens inloggningstillstånd

En vykomponent består av två delar:

  • Klassen, som vanligtvis härleds från ViewComponent
  • Resultatet som returneras är vanligtvis en vy.

Precis som kontrollanter kan en vykomponent vara en POCO, men de flesta utvecklare drar nytta av de metoder och egenskaper som är tillgängliga genom att härleda från ViewComponent.

När du överväger att visa komponenter som uppfyller en apps specifikationer bör du överväga att använda Razor komponenter i stället. Razor komponenter kombinerar också markering med C#-kod för att skapa återanvändbara användargränssnittsenheter. Razor komponenter är utformade för utvecklarproduktivitet när du tillhandahåller logik och sammansättning för användargränssnittet på klientsidan. Mer information finns i ASP.NET Core-komponenterRazor. Information om hur du införlivar Razor komponenter i en MVC- eller Razor Pages-app finns i Integrera ASP.NET Core-komponenter Razor med MVC eller Razor Sidor.

Skapa en vykomponent

Det här avsnittet innehåller kraven på hög nivå för att skapa en vykomponent. Senare i artikeln undersöker vi varje steg i detalj och skapar en vykomponent.

Klassen för vykomponent

En vykomponentklass kan skapas av något av följande:

Precis som kontrollanter måste visningskomponenter vara offentliga, icke-kapslade och icke-abstrakta klasser. Vykomponentens namn är klassnamnet med suffixet borttaget ViewComponent . Det kan också uttryckligen anges med hjälp av Name egenskapen .

En vykomponentklass:

Om du vill förhindra att en klass som har ett skiftlägeskänsligt ViewComponent suffix behandlas som en vykomponent, dekorerar du klassen med [NonViewComponent] attributet:

using Microsoft.AspNetCore.Mvc;

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

Visa komponentmetoder

En vykomponent definierar sin logik i en:

  • InvokeAsync -metod som returnerar Task<IViewComponentResult>.
  • Invoke synkron metod som returnerar en IViewComponentResult.

Parametrarna kommer direkt från anrop av vykomponenten, inte från modellbindningen. En vykomponent hanterar aldrig en begäran direkt. Vanligtvis initierar en vykomponent en modell och skickar den till en vy genom att anropa View metoden. Sammanfattningsvis, se komponentmetoder:

  • Definiera en InvokeAsync metod som returnerar en Task<IViewComponentResult> eller en synkron Invoke metod som returnerar en IViewComponentResult.
  • Initierar vanligtvis en modell och skickar den till en vy genom att anropa metoden ViewComponent.View .
  • Parametrarna kommer från anropande metod, inte HTTP. Det finns ingen modellbindning.
  • Kan inte nås direkt som en HTTP-slutpunkt. De anropas vanligtvis i en vy. En vykomponent hanterar aldrig en begäran.
  • Är överbelastade på signaturen i stället för någon information från den aktuella HTTP-begäran.

Visa sökväg

Runtime-miljön söker efter vyn i följande sökvägar:

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

Sökvägen gäller för projekt med hjälp av kontroller + vyer och Razor Sidor.

Standardvynamnet för en vykomponent är Default, vilket innebär att visningsfiler vanligtvis heter Default.cshtml. Ett annat vynamn kan anges när du skapar resultatet av vykomponenten eller när metoden anropas View .

Vi rekommenderar att du namnger vyfilen Default.cshtml och använder sökvägen Views/Shared/Components/{View Component Name}/{View Name} . Vykomponenten PriorityList som används i det här exemplet används Views/Shared/Components/PriorityList/Default.cshtml för vykomponentvyn.

Anpassa sökvägen för vyer

För att anpassa sökvägen för vyer, ändra Razor-kollektionen ViewLocationFormats. Om du till exempel vill söka efter vyer i sökvägen /Components/{View Component Name}/{View Name}lägger du till ett nytt objekt i samlingen:

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.

I föregående kod representerar platshållaren {0} sökvägen Components/{View Component Name}/{View Name}.

Anropa en vykomponent

Om du vill använda vykomponenten anropar du följande i en vy:

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

Parametrarna skickas till InvokeAsync metoden. Vykomponenten PriorityList som utvecklats i artikeln anropas från Views/ToDo/Index.cshtml vyfilen. I följande kod InvokeAsync anropas metoden med två parametrar:

</table>

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

Anropa en vykomponent som en Tag Helper

En vykomponent kan anropas som en 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-klass- och metodparametrar för Tag Helpers översätts till deras kebabfall. Tagghjälpen för att anropa en vykomponent använder elementet <vc></vc> . Vykomponenten anges på följande sätt:

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

Om du vill använda en vykomponent som Tag Helper registrerar du sammansättningen som innehåller vykomponenten @addTagHelper med hjälp av direktivet. Om vykomponenten finns i en sammansättning med namnet MyWebApplägger du till följande direktiv i _ViewImports.cshtml filen:

@addTagHelper *, MyWebApp

En vykomponent kan registreras som en Tag Helper för alla filer som refererar till vykomponenten. Mer information om hur du registrerar Tag Helpers finns i Managing Tag Helper Scope.

Metoden InvokeAsync som används i denna handledning:

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

I föregående markering blir vykomponenten PriorityList till priority-list. Parametrarna till vykomponenten skickas som attribut i kebabformat.

Anropa en vykomponent direkt från en kontrollant

Visningskomponenter anropas vanligtvis från en vy, men de kan anropas direkt från en kontrollantmetod. Även om visningskomponenter inte definierar slutpunkter som kontrollanter, kan en kontrollantåtgärd som returnerar innehållet i en ViewComponentResult implementeras.

I följande exempel anropas vykomponenten direkt från kontrollanten:

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

Skapa en grundläggande vykomponent

Ladda ned, skapa och testa startkoden. Det är ett grundläggande projekt med en ToDo kontrollant som visar en lista över ToDo-objekt .

Lista över ToDos

Uppdatera kontrollanten för att överföra prioritets- och slutförandestatus

Uppdatera metoden för att använda parametrar för Index prioritets- och slutförandestatus:

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

Lägga till en ViewComponent-klass

Lägg till en ViewComponent-klass i 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();
    }
}

Anmärkningar om koden:

  • Visa komponentklasser kan finnas i valfri mapp i projektet.

  • Eftersom klassnamnet PriorityListViewComponent slutar med suffixet ViewComponent använder körningen strängen PriorityList när du refererar till klasskomponenten från en vy.

  • Attributet [ViewComponent] kan ändra namnet som används för att referera till en vykomponent. Klassen kan till exempel ha fått namnet XYZ med följande [ViewComponent] attribut:

    [ViewComponent(Name = "PriorityList")]
       public class XYZ : ViewComponent
    
  • Attributet [ViewComponent] i föregående kod instruerar visningskomponentväljaren att använda:

    • När du letar efter de vyer som är associerade med komponenten använd namnet PriorityList.
    • Strängen "PriorityList" när du refererar till klasskomponenten från en vy.
  • Komponenten använder beroendeinmatning för att göra datakontexten tillgänglig.

  • InvokeAsync exponerar en metod som kan anropas från en vy och kan ta ett godtyckligt antal argument.

  • Metoden InvokeAsync returnerar den uppsättning ToDo objekt som uppfyller parametrarna isDone och maxPriority .

Skapa vykomponenten Razor

  • Skapa mappen Views/Shared/Components . Den här mappen måste ha namnet Komponenter.

  • Skapa mappen Views/Shared/Components/PriorityList . Det här mappnamnet måste matcha namnet på vykomponentklassen eller namnet på klassen minus suffixet. ViewComponent Om attributet används måste klassnamnet matcha attributbeteckningen.

  • Skapa en Views/Shared/Components/PriorityList/Default.cshtmlRazor vy:

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

    Vyn Razor tar en lista över TodoItem och visar dem. Om visningskomponentmetoden InvokeAsync inte skickar namnet på vyn används Standard för visningsnamnet efter konvention. Om du vill åsidosätta standardformateringen för en specifik kontrollant lägger du till en vy i den kontrollantspecifika vymappen (till exempel Views/ToDo/Components/PriorityList/Default.cshtml).

    Om vykomponenten är kontrollantspecifik kan den läggas till i den kontrollantspecifika mappen. Till exempel Views/ToDo/Components/PriorityList/Default.cshtml är styrenhetsspecifik.

  • Lägg till ett div innehållande ett anrop till prioritetslistkomponenten längst ned i Views/ToDo/index.cshtml filen:

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

Pålägget @await Component.InvokeAsync visar syntaxen för att anropa visningskomponenter. Det första argumentet är namnet på komponenten som vi vill anropa. Efterföljande parametrar skickas till komponenten. InvokeAsync kan ta ett godtyckligt antal argument.

Testa appen. Följande bild visar ToDo-listan och prioritetsobjekten:

att göra-lista och prioritetsobjekt

Vykomponenten kan anropas direkt från kontrollanten:

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

prioritetsobjekt från IndexVC-åtgärd

Ange ett vykomponentnamn

En komplex vykomponent kan behöva ange en icke-standardvy under vissa förhållanden. Följande kod visar hur du anger "PVC"-vyn från InvokeAsync metoden. InvokeAsync Uppdatera metoden i PriorityListViewComponent klassen.

public async Task<IViewComponentResult> InvokeAsync(
                                           int maxPriority, bool isDone)
{
    string MyView = "Default";
    // If asking for all completed tasks, render with the "PVC" view.
    if (maxPriority > 3 && isDone == true)
    {
        MyView = "PVC";
    }
    var items = await GetItemsAsync(maxPriority, isDone);
    return View(MyView, items);
}

Views/Shared/Components/PriorityList/Default.cshtml Kopiera filen till en vy med namnet Views/Shared/Components/PriorityList/PVC.cshtml. Lägg till en överskrift som anger att PVC-vyn används.

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

Kör appen och verifiera PVC-vyn.

Komponent för prioritetsvy

Om PVC-vyn inte återges kontrollerar du att vykomponenten med prioriteten 4 eller högre anropas.

Granska visningssökvägen

  • Ändra prioritetsparametern till tre eller mindre så att prioritetsvyn inte returneras.

  • Byt tillfälligt namn på Views/ToDo/Components/PriorityList/Default.cshtml till 1Default.cshtml.

  • Testa appen, följande fel inträffar:

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

  • Lägg till uppmärkning i vyn för komponenten Delad ToDo för att indikera att vyn kommer från den Delade mappen.

  • Testa vyn för den delade komponenten.

ToDo-utdata med delad vy för komponenter

Undvik hårdkodade strängar

För att kompilera tidssäkerhet ersätter du det hårdkodade vykomponentnamnet med klassnamnet. Uppdatera PriorityListViewComponent.cs-filen så att den inte använder suffixet "ViewComponent":

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ViewComponentSample.Models;

namespace ViewComponentSample.ViewComponents;

public class PriorityList : ViewComponent
{
    private readonly ToDoContext db;

    public PriorityList(ToDoContext context)
    {
        db = context;
    }

    public async Task<IViewComponentResult> InvokeAsync(
                                               int maxPriority, bool isDone)
    {
        var items = await GetItemsAsync(maxPriority, isDone);
        return View(items);
    }

    private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
    {
        return db!.ToDo!.Where(x => x.IsDone == isDone &&
                             x.Priority <= maxPriority).ToListAsync();
    }
}

Vyfilen:

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

En överlagring av Component.InvokeAsync metoden som tar en CLR-typ använder operatorn typeof :

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

Utföra synkront arbete

Ramverket hanterar att anropa en synkron Invoke metod om asynkront arbete inte krävs. Följande metod skapar en synkron Invoke vykomponent:

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

Vykomponentens Razor-fil:

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

Vykomponenten anropas i en Razor fil (till exempel Views/Home/Index.cshtml) med någon av följande metoder:

Om du vill använda IViewComponentHelper metoden anropar du Component.InvokeAsync:

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

Om du vill använda Tag Helper registrerar du sammansättningen som innehåller vykomponenten @addTagHelper med hjälp av direktivet (vykomponenten finns i en sammansättning med namnet MyWebApp):

@addTagHelper *, MyWebApp

Använd visningskomponenten Tag Helper i markeringsfilen Razor :

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

Metodsignaturen PriorityList.Invoke för är synkron, men Razor söker efter och anropar metoden med Component.InvokeAsync i markeringsfilen.

Ytterligare resurser

Visa komponenter

Visningskomponenter liknar partiella vyer, men de är mycket kraftfullare. Visa komponenter använder inte modellbindning, de är beroende av de data som skickas när du anropar vykomponenten. Den här artikeln skrevs med hjälp av kontroller och vyer, men vykomponenter fungerar med Razor Sidor.

En vykomponent:

  • Renderar ett segment i stället för ett helt svar.
  • Inkluderar samma fördelar med ansvarsseparation och testbarhet som finns mellan en controller och en vy.
  • Kan ha parametrar och affärslogik.
  • Anropas vanligtvis från en layoutsida.

Vykomponenter är avsedda för situationer med återanvändbar renderingslogik som är för komplex för en partiell vy, till exempel:

  • Dynamiska navigeringsmenyer
  • Taggmoln, där det gör en sökning i databasen
  • Inloggningspanel
  • Kundvagn
  • Nyligen publicerade artiklar
  • Sidofältsinnehåll på en blogg
  • En inloggningspanel som återges på varje sida och visar antingen länkarna för att logga ut eller logga in, beroende på användarens inloggningstillstånd

En vykomponent består av två delar:

  • Klassen, som vanligtvis härleds från ViewComponent
  • Resultatet som returneras är vanligtvis en vy.

Precis som kontrollanter kan en vykomponent vara en POCO, men de flesta utvecklare drar nytta av de metoder och egenskaper som är tillgängliga genom att härleda från ViewComponent.

När du överväger att visa komponenter som uppfyller en apps specifikationer bör du överväga att använda Razor komponenter i stället. Razor komponenter kombinerar också markering med C#-kod för att skapa återanvändbara användargränssnittsenheter. Razor komponenter är utformade för utvecklarproduktivitet när du tillhandahåller logik och sammansättning för användargränssnittet på klientsidan. Mer information finns i ASP.NET Core-komponenterRazor. Information om hur du införlivar Razor komponenter i en MVC- eller Razor Pages-app finns i Integrera ASP.NET Core-komponenter Razor med MVC eller Razor Sidor.

Skapa en vykomponent

Det här avsnittet innehåller kraven på hög nivå för att skapa en vykomponent. Senare i artikeln undersöker vi varje steg i detalj och skapar en vykomponent.

Klassen för vykomponent

En vykomponentklass kan skapas av något av följande:

Precis som kontrollanter måste visningskomponenter vara offentliga, icke-kapslade och icke-abstrakta klasser. Vykomponentens namn är klassnamnet med suffixet borttaget ViewComponent . Det kan också uttryckligen anges med hjälp av Name egenskapen .

En vykomponentklass:

Om du vill förhindra att en klass som har ett skiftlägeskänsligt ViewComponent suffix behandlas som en vykomponent, dekorerar du klassen med [NonViewComponent] attributet:

using Microsoft.AspNetCore.Mvc;

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

Visa komponentmetoder

En vykomponent definierar sin logik i en:

  • InvokeAsync -metod som returnerar Task<IViewComponentResult>.
  • Invoke synkron metod som returnerar en IViewComponentResult.

Parametrarna kommer direkt från anrop av vykomponenten, inte från modellbindningen. En vykomponent hanterar aldrig en begäran direkt. Vanligtvis initierar en vykomponent en modell och skickar den till en vy genom att anropa View metoden. Sammanfattningsvis, se komponentmetoder:

  • Definiera en InvokeAsync metod som returnerar en Task<IViewComponentResult> eller en synkron Invoke metod som returnerar en IViewComponentResult.
  • Initierar vanligtvis en modell och skickar den till en vy genom att anropa metoden ViewComponent.View .
  • Parametrarna kommer från anropande metod, inte HTTP. Det finns ingen modellbindning.
  • Kan inte nås direkt som en HTTP-slutpunkt. De anropas vanligtvis i en vy. En vykomponent hanterar aldrig en begäran.
  • Är överbelastade på signaturen i stället för någon information från den aktuella HTTP-begäran.

Visa sökväg

Runtime-miljön söker efter vyn i följande sökvägar:

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

Sökvägen gäller för projekt med hjälp av kontroller + vyer och Razor Sidor.

Standardvynamnet för en vykomponent är Default, vilket innebär att visningsfiler vanligtvis heter Default.cshtml. Ett annat vynamn kan anges när du skapar resultatet av vykomponenten eller när metoden anropas View .

Vi rekommenderar att du namnger vyfilen Default.cshtml och använder sökvägen Views/Shared/Components/{View Component Name}/{View Name} . Vykomponenten PriorityList som används i det här exemplet används Views/Shared/Components/PriorityList/Default.cshtml för vykomponentvyn.

Anpassa sökvägen för vyer

För att anpassa sökvägen för vyer, ändra Razor-kollektionen ViewLocationFormats. Om du till exempel vill söka efter vyer i sökvägen /Components/{View Component Name}/{View Name}lägger du till ett nytt objekt i samlingen:

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.

I föregående kod representerar platshållaren {0} sökvägen Components/{View Component Name}/{View Name}.

Anropa en vykomponent

Om du vill använda vykomponenten anropar du följande i en vy:

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

Parametrarna skickas till InvokeAsync metoden. Vykomponenten PriorityList som utvecklats i artikeln anropas från Views/ToDo/Index.cshtml vyfilen. I följande kod InvokeAsync anropas metoden med två parametrar:

</table>

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

Anropa en vykomponent som en Tag Helper

En vykomponent kan anropas som en 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-klass- och metodparametrar för Tag Helpers översätts till deras kebabfall. Tagghjälpen för att anropa en vykomponent använder elementet <vc></vc> . Vykomponenten anges på följande sätt:

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

Om du vill använda en vykomponent som Tag Helper registrerar du sammansättningen som innehåller vykomponenten @addTagHelper med hjälp av direktivet. Om vykomponenten finns i en sammansättning med namnet MyWebApplägger du till följande direktiv i _ViewImports.cshtml filen:

@addTagHelper *, MyWebApp

En vykomponent kan registreras som en Tag Helper för alla filer som refererar till vykomponenten. Mer information om hur du registrerar Tag Helpers finns i Managing Tag Helper Scope.

Metoden InvokeAsync som används i denna handledning:

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

I föregående markering blir vykomponenten PriorityList till priority-list. Parametrarna till vykomponenten skickas som attribut i kebabformat.

Anropa en vykomponent direkt från en kontrollant

Visningskomponenter anropas vanligtvis från en vy, men de kan anropas direkt från en kontrollantmetod. Även om visningskomponenter inte definierar slutpunkter som kontrollanter, kan en kontrollantåtgärd som returnerar innehållet i en ViewComponentResult implementeras.

I följande exempel anropas vykomponenten direkt från kontrollanten:

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

Skapa en grundläggande vykomponent

Ladda ned, skapa och testa startkoden. Det är ett grundläggande projekt med en ToDo kontrollant som visar en lista över ToDo-objekt .

Lista över ToDos

Uppdatera kontrollanten för att överföra prioritets- och slutförandestatus

Uppdatera metoden för att använda parametrar för Index prioritets- och slutförandestatus:

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

Lägga till en ViewComponent-klass

Lägg till en ViewComponent-klass i 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();
    }
}

Anmärkningar om koden:

  • Visa komponentklasser kan finnas i valfri mapp i projektet.

  • Eftersom klassnamnet PriorityListViewComponent slutar med suffixet ViewComponent använder körningen strängen PriorityList när du refererar till klasskomponenten från en vy.

  • Attributet [ViewComponent] kan ändra namnet som används för att referera till en vykomponent. Klassen kan till exempel ha fått namnet XYZ med följande [ViewComponent] attribut:

    [ViewComponent(Name = "PriorityList")]
       public class XYZ : ViewComponent
    
  • Attributet [ViewComponent] i föregående kod instruerar visningskomponentväljaren att använda:

    • När du letar efter de vyer som är associerade med komponenten använd namnet PriorityList.
    • Strängen "PriorityList" när du refererar till klasskomponenten från en vy.
  • Komponenten använder beroendeinmatning för att göra datakontexten tillgänglig.

  • InvokeAsync exponerar en metod som kan anropas från en vy och kan ta ett godtyckligt antal argument.

  • Metoden InvokeAsync returnerar den uppsättning ToDo objekt som uppfyller parametrarna isDone och maxPriority .

Skapa vykomponenten Razor

  • Skapa mappen Views/Shared/Components . Den här mappen måste ha namnet Komponenter.

  • Skapa mappen Views/Shared/Components/PriorityList . Det här mappnamnet måste matcha namnet på vykomponentklassen eller namnet på klassen minus suffixet. ViewComponent Om attributet används måste klassnamnet matcha attributbeteckningen.

  • Skapa en Views/Shared/Components/PriorityList/Default.cshtmlRazor vy:

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

    Vyn Razor tar en lista över TodoItem och visar dem. Om visningskomponentmetoden InvokeAsync inte skickar namnet på vyn används Standard för visningsnamnet efter konvention. Om du vill åsidosätta standardformateringen för en specifik kontrollant lägger du till en vy i den kontrollantspecifika vymappen (till exempel Views/ToDo/Components/PriorityList/Default.cshtml).

    Om vykomponenten är kontrollantspecifik kan den läggas till i den kontrollantspecifika mappen. Till exempel Views/ToDo/Components/PriorityList/Default.cshtml är styrenhetsspecifik.

  • Lägg till ett div innehållande ett anrop till prioritetslistkomponenten längst ned i Views/ToDo/index.cshtml filen:

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

Pålägget @await Component.InvokeAsync visar syntaxen för att anropa visningskomponenter. Det första argumentet är namnet på komponenten som vi vill anropa. Efterföljande parametrar skickas till komponenten. InvokeAsync kan ta ett godtyckligt antal argument.

Testa appen. Följande bild visar ToDo-listan och prioritetsobjekten:

att göra-lista och prioritetsobjekt

Vykomponenten kan anropas direkt från kontrollanten:

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

prioritetsobjekt från IndexVC-åtgärd

Ange ett vykomponentnamn

En komplex vykomponent kan behöva ange en icke-standardvy under vissa förhållanden. Följande kod visar hur du anger "PVC"-vyn från InvokeAsync metoden. InvokeAsync Uppdatera metoden i PriorityListViewComponent klassen.

public async Task<IViewComponentResult> InvokeAsync(
                                           int maxPriority, bool isDone)
{
    string MyView = "Default";
    // If asking for all completed tasks, render with the "PVC" view.
    if (maxPriority > 3 && isDone == true)
    {
        MyView = "PVC";
    }
    var items = await GetItemsAsync(maxPriority, isDone);
    return View(MyView, items);
}

Views/Shared/Components/PriorityList/Default.cshtml Kopiera filen till en vy med namnet Views/Shared/Components/PriorityList/PVC.cshtml. Lägg till en överskrift som anger att PVC-vyn används.

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

Kör appen och verifiera PVC-vyn.

Komponent för prioritetsvy

Om PVC-vyn inte återges kontrollerar du att vykomponenten med prioriteten 4 eller högre anropas.

Granska visningssökvägen

  • Ändra prioritetsparametern till tre eller mindre så att prioritetsvyn inte returneras.

  • Byt tillfälligt namn på Views/ToDo/Components/PriorityList/Default.cshtml till 1Default.cshtml.

  • Testa appen, följande fel inträffar:

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

  • Lägg till uppmärkning i vyn för komponenten Delad ToDo för att indikera att vyn kommer från den Delade mappen.

  • Testa vyn för den delade komponenten.

ToDo-utdata med delad vy för komponenter

Undvik hårdkodade strängar

För att kompilera tidssäkerhet ersätter du det hårdkodade vykomponentnamnet med klassnamnet. Uppdatera PriorityListViewComponent.cs-filen så att den inte använder suffixet "ViewComponent":

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using ViewComponentSample.Models;

namespace ViewComponentSample.ViewComponents;

public class PriorityList : ViewComponent
{
    private readonly ToDoContext db;

    public PriorityList(ToDoContext context)
    {
        db = context;
    }

    public async Task<IViewComponentResult> InvokeAsync(
                                               int maxPriority, bool isDone)
    {
        var items = await GetItemsAsync(maxPriority, isDone);
        return View(items);
    }

    private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
    {
        return db!.ToDo!.Where(x => x.IsDone == isDone &&
                             x.Priority <= maxPriority).ToListAsync();
    }
}

Vyfilen:

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

En överlagring av Component.InvokeAsync metoden som tar en CLR-typ använder operatorn typeof :

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

Utföra synkront arbete

Ramverket hanterar att anropa en synkron Invoke metod om asynkront arbete inte krävs. Följande metod skapar en synkron Invoke vykomponent:

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

Vykomponentens Razor-fil:

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

Vykomponenten anropas i en Razor fil (till exempel Views/Home/Index.cshtml) med någon av följande metoder:

Om du vill använda IViewComponentHelper metoden anropar du Component.InvokeAsync:

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

Om du vill använda Tag Helper registrerar du sammansättningen som innehåller vykomponenten @addTagHelper med hjälp av direktivet (vykomponenten finns i en sammansättning med namnet MyWebApp):

@addTagHelper *, MyWebApp

Använd visningskomponenten Tag Helper i markeringsfilen Razor :

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

Metodsignaturen PriorityList.Invoke för är synkron, men Razor söker efter och anropar metoden med Component.InvokeAsync i markeringsfilen.

Ytterligare resurser

Visa eller ladda ned exempelkod (hur du laddar ned)

Visa komponenter

Visningskomponenter liknar partiella vyer, men de är mycket kraftfullare. Visa komponenter använder inte modellbindning och är bara beroende av de data som tillhandahålls när de anropas till den. Den här artikeln skrevs med hjälp av kontrollanter och vyer, men visningskomponenter fungerar också med Razor Sidor.

En vykomponent:

  • Renderar ett segment i stället för ett helt svar.
  • Inkluderar samma fördelar med ansvarsseparation och testbarhet som finns mellan en controller och en vy.
  • Kan ha parametrar och affärslogik.
  • Anropas vanligtvis från en layoutsida.

Vykomponenter är avsedda överallt där du har återanvändbar renderingslogik som är för komplex för en partiell vy, till exempel:

  • Dynamiska navigeringsmenyer
  • Taggmoln (där det hämtar information från databasen)
  • Inloggningspanel
  • Kundvagn
  • Nyligen publicerade artiklar
  • Innehåll i sidofältet på en typisk blogg
  • En inloggningspanel som återges på varje sida och visar antingen länkarna för att logga ut eller logga in, beroende på användarens inloggningstillstånd

En vykomponent består av två delar: klassen (vanligtvis härledd från ViewComponent) och resultatet den returnerar (vanligtvis en vy). Precis som kontrollanter kan en vykomponent vara en POCO, men de flesta utvecklare drar nytta av de metoder och egenskaper som är tillgängliga genom att härleda från ViewComponent.

När du överväger att visa komponenter som uppfyller en apps specifikationer bör du överväga att använda Razor komponenter i stället. Razor komponenter kombinerar också markering med C#-kod för att skapa återanvändbara användargränssnittsenheter. Razor komponenter är utformade för utvecklarproduktivitet när du tillhandahåller logik och sammansättning för användargränssnittet på klientsidan. Mer information finns i ASP.NET Core-komponenterRazor. Information om hur du införlivar Razor komponenter i en MVC- eller Razor Pages-app finns i Integrera ASP.NET Core-komponenter Razor med MVC eller Razor Sidor.

Skapa en vykomponent

Det här avsnittet innehåller kraven på hög nivå för att skapa en vykomponent. Senare i artikeln undersöker vi varje steg i detalj och skapar en vykomponent.

Klassen för vykomponent

En vykomponentklass kan skapas av något av följande:

  • Härled från ViewComponent
  • Dekorera en klass med [ViewComponent] attributet eller härleda från en klass med [ViewComponent] attributet
  • Skapa en klass där namnet slutar med suffixet ViewComponent

Precis som kontrollanter måste visningskomponenter vara offentliga, icke-kapslade och icke-abstrakta klasser. Vykomponentens namn är klassnamnet med "ViewComponent"-suffixet borttaget. Det kan också uttryckligen anges med hjälp av ViewComponentAttribute.Name egenskapen .

En vykomponentklass:

Om du vill stoppa en klass som har ett skiftlägesokänsligt ViewComponent-suffix från att behandlas som en vykomponent, dekorerar du klassen med attributet [NonViewComponent] :

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

Visa komponentmetoder

En vykomponent definierar dess logik i en InvokeAsync metod som returnerar en Task<IViewComponentResult> eller i en synkron Invoke metod som returnerar en IViewComponentResult. Parametrarna kommer direkt från anrop av vykomponenten, inte från modellbindningen. En vykomponent hanterar aldrig en begäran direkt. Vanligtvis initierar en vykomponent en modell och skickar den till en vy genom att anropa View metoden. Sammanfattningsvis, se komponentmetoder:

  • Definiera en InvokeAsync metod som returnerar en Task<IViewComponentResult> eller en synkron Invoke metod som returnerar en IViewComponentResult.
  • Initierar vanligtvis en modell och skickar den till en vy genom att anropa ViewComponentView metoden.
  • Parametrarna kommer från anropande metod, inte HTTP. Det finns ingen modellbindning.
  • Kan inte nås direkt som en HTTP-slutpunkt. Dessa anropas från din kod (vanligtvis i en vy). En vykomponent hanterar aldrig en begäran.
  • Är överbelastade på signaturen i stället för någon information från den aktuella HTTP-begäran.

Visa sökväg

Runtime-miljön söker efter vyn i följande sökvägar:

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

Sökvägen gäller för projekt med hjälp av kontroller + vyer och Razor Sidor.

Standardvynamnet för en vykomponent är Standard, vilket innebär att visningsfilen vanligtvis heter Default.cshtml. Du kan ange ett annat vynamn när du skapar visningskomponentresultatet eller när du anropar View metoden.

Vi rekommenderar att du namnger vyfilen Default.cshtml och använder sökvägen Views/Shared/Components/{View Component Name}/{View Name} . Vykomponenten PriorityList som används i det här exemplet används Views/Shared/Components/PriorityList/Default.cshtml för vykomponentvyn.

Anpassa sökvägen för vyer

För att anpassa sökvägen för vyer, ändra Razor-kollektionen ViewLocationFormats. Om du till exempel vill söka efter vyer i sökvägen "/Components/{View Component Name}/{View Name}" lägger du till ett nytt objekt i samlingen:

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

I föregående kod representerar platshållaren "{0}" sökvägen "Komponenter/{Visa komponentnamn}/{Vynamn}".

Anropa en vykomponent

Om du vill använda vykomponenten anropar du följande i en vy:

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

Parametrarna skickas till InvokeAsync metoden. Vykomponenten PriorityList som utvecklats i artikeln anropas från Views/ToDo/Index.cshtml vyfilen. I det följande kallas metoden InvokeAsync med två parametrar:

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

Anropa en vykomponent som en Tag Helper

För ASP.NET Core 1.1 och senare kan du anropa en vykomponent som en Tag Helper:

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

Pascal-cased-klass- och metodparametrar för Tag Helpers översätts till deras kebabfall. Tagghjälpen för att anropa en vykomponent använder elementet <vc></vc> . Vykomponenten anges på följande sätt:

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

Om du vill använda en vykomponent som Tag Helper registrerar du sammansättningen som innehåller vykomponenten @addTagHelper med hjälp av direktivet. Om din vykomponent finns i en sammansättning med namnet MyWebApplägger du till följande direktiv i _ViewImports.cshtml filen:

@addTagHelper *, MyWebApp

Du kan registrera en vykomponent som en Tag Helper för alla filer som refererar till vykomponenten. Mer information om hur du registrerar Tag Helpers finns i Managing Tag Helper Scope.

Metoden InvokeAsync som används i denna handledning:

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

I Tag Helper-uppmärkning:

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

I exemplet ovan PriorityList blir priority-listvykomponenten . Parametrarna till vykomponenten skickas som attribut i kebabformat.

Anropa en vykomponent direkt från en kontroller

Visningskomponenter anropas vanligtvis från en vy, men du kan anropa dem direkt från en kontrollantmetod. Även om visningskomponenter inte definierar slutpunkter som kontrollanter, kan du enkelt implementera en kontrollantåtgärd som returnerar innehållet i en ViewComponentResult.

I det här exemplet anropas vykomponenten direkt från kontrollanten:

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

Genomgång: Skapa en enkel vykomponent

Ladda ned, skapa och testa startkoden. Det är ett enkelt projekt med en ToDo kontrollant som visar en lista över ToDo-objekt .

Lista över ToDos

Lägga till en ViewComponent-klass

Skapa en ViewComponents-mapp och lägg till följande PriorityListViewComponent klass:

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

Anmärkningar om koden:

  • Visa komponentklasser kan finnas i valfri mapp i projektet.

  • Eftersom klassnamnet PriorityListViewComponent slutar med suffixet ViewComponent använder körningen strängen PriorityList när du refererar till klasskomponenten från en vy.

  • Attributet [ViewComponent] kan ändra namnet som används för att referera till en vykomponent. Klassen kan till exempel ha fått namnet XYZ med attributet ViewComponent :

    [ViewComponent(Name = "PriorityList")]
       public class XYZ : ViewComponent
    
  • Attributet [ViewComponent] i föregående kod instruerar visningskomponentväljaren att använda:

    • När du letar efter de vyer som är associerade med komponenten använd namnet PriorityList.
    • Strängen "PriorityList" när du refererar till klasskomponenten från en vy.
  • Komponenten använder beroendeinmatning för att göra datakontexten tillgänglig.

  • InvokeAsync exponerar en metod som kan anropas från en vy och kan ta ett godtyckligt antal argument.

  • Metoden InvokeAsync returnerar den uppsättning ToDo objekt som uppfyller parametrarna isDone och maxPriority .

Skapa vykomponenten Razor

  • Skapa mappen Views/Shared/Components . Den här mappen måste ha namnet Components.

  • Skapa mappen Views/Shared/Components/PriorityList . Det här mappnamnet måste matcha namnet på vykomponentklassen eller namnet på klassen minus suffixet (om vi följde konventionen och använde suffixet ViewComponent i klassnamnet). Om du använde ViewComponent attributet måste klassnamnet matcha attributbeteckningen.

  • Skapa en Views/Shared/Components/PriorityList/Default.cshtmlRazor vy:

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

    Vyn Razor tar en lista över TodoItem och visar dem. Om visningskomponentmetoden InvokeAsync inte skickar namnet på vyn (som i vårt exempel) används Standard för visningsnamnet efter konvention. Senare i handledningen visar jag hur du skickar namnet på vyn. Om du vill åsidosätta standardformateringen för en specifik kontrollant lägger du till en vy i den kontrollantspecifika vymappen (till exempel Views/ToDo/Components/PriorityList/Default.cshtml).

    Om vykomponenten är kontrollantspecifik kan du lägga till den i den kontrollantspecifika mappen (Views/ToDo/Components/PriorityList/Default.cshtml).

  • Lägg till ett div innehållande ett anrop till prioritetslistkomponenten längst ned i Views/ToDo/index.cshtml filen:

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

Pålägget @await Component.InvokeAsync visar syntaxen för att anropa visningskomponenter. Det första argumentet är namnet på komponenten som vi vill anropa. Efterföljande parametrar skickas till komponenten. InvokeAsync kan ta ett godtyckligt antal argument.

Testa appen. Följande bild visar ToDo-listan och prioritetsobjekten:

att göra-lista och prioritetsobjekt

Du kan också anropa vykomponenten direkt från kontrollanten:

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

prioritetsobjekt från IndexVC-åtgärd

Ange ett visningsnamn

En komplex vykomponent kan behöva ange en icke-standardvy under vissa förhållanden. Följande kod visar hur du anger "PVC"-vyn från InvokeAsync metoden. InvokeAsync Uppdatera metoden i PriorityListViewComponent klassen.

public async Task<IViewComponentResult> InvokeAsync(
    int maxPriority, bool isDone)
{
    string MyView = "Default";
    // If asking for all completed tasks, render with the "PVC" view.
    if (maxPriority > 3 && isDone == true)
    {
        MyView = "PVC";
    }
    var items = await GetItemsAsync(maxPriority, isDone);
    return View(MyView, items);
}

Views/Shared/Components/PriorityList/Default.cshtml Kopiera filen till en vy med namnet Views/Shared/Components/PriorityList/PVC.cshtml. Lägg till en överskrift som anger att PVC-vyn används.

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

Uppdatera Views/ToDo/Index.cshtml:

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

Kör appen och verifiera PVC-vyn.

Komponent för prioritetsvy

Om PVC-vyn inte återges, kontrollera att du anropar vykomponenten med en prioritet på 4 eller högre.

Granska visningssökvägen

  • Ändra prioritetsparametern till tre eller mindre så att prioritetsvyn inte returneras.

  • Byt tillfälligt namn på Views/ToDo/Components/PriorityList/Default.cshtml till 1Default.cshtml.

  • Testa appen. Du får följande fel:

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

  • Lägg till uppmärkning i vyn för komponenten Delad ToDo för att indikera att vyn kommer från den Delade mappen.

  • Testa vyn för den delade komponenten.

ToDo-utdata med delad vy för komponenter

Undvika hårdkodade strängar

Om du vill kompilera tidssäkerhet kan du ersätta det hårdkodade vykomponentnamnet med klassnamnet. Skapa vykomponenten utan suffixet "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();
        }
    }
}

Lägg till en using instruktion i visningsfilen Razor och använd operatorn 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>

Du kan använda en överlagring av metoden Component.InvokeAsync för att ta en CLR-typ. Kom ihåg att använda operatorn typeof i det här fallet:

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

Utföra synkront arbete

Ramverket hanterar att anropa en synkron Invoke metod om du inte behöver utföra asynkront arbete. Följande metod skapar en synkron Invoke vykomponent:

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

Vykomponentens Razor fil visar de strängar som skickas till Invoke metoden (Views/Home/Components/PriorityList/Default.cshtml):

@model List<string>

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

Vykomponenten anropas i en Razor fil (till exempel Views/Home/Index.cshtml) med någon av följande metoder:

Om du vill använda IViewComponentHelper metoden anropar du Component.InvokeAsync:

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

Om du vill använda Tag Helper registrerar du sammansättningen som innehåller vykomponenten @addTagHelper med hjälp av direktivet (vykomponenten finns i en sammansättning med namnet MyWebApp):

@addTagHelper *, MyWebApp

Använd visningskomponenten Tag Helper i markeringsfilen Razor :

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

Metodsignaturen PriorityList.Invoke för är synkron, men Razor söker efter och anropar metoden med Component.InvokeAsync i markeringsfilen.

Alla vykomponentparametrar krävs

Varje parameter i en vykomponent är ett obligatoriskt attribut. Se det här GitHub-problemet. Om någon parameter utelämnas:

  • Metodsignaturen InvokeAsync matchar inte, därför körs inte metoden.
  • ViewComponent renderar inga markeringar.
  • Inga fel kastas.

Ytterligare resurser