Afhankelijkheidsinjectie in weergaven in ASP.NET Core
ASP.NET Core ondersteunt afhankelijkheidsinjectie in views. Dit kan handig zijn voor weergavespecifieke services, zoals lokalisatie of gegevens die alleen nodig zijn voor het invullen van weergave-elementen. De meeste weergaven van gegevens moeten worden doorgegeven vanuit de controller.
voorbeeldcode bekijken of downloaden (hoe te downloaden)
Configuratie-injectie
De waarden in instellingenbestanden, zoals appsettings.json
en appsettings.Development.json
, kunnen in een weergave worden geïnjecteerd. Bekijk de appsettings.Development.json
uit de voorbeeldcode:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"MyRoot": {
"MyParent": {
"MyChildName": "Joe"
}
}
}
De volgende markup geeft de configuratiewaarde weer in een Razor Pagina's-weergave.
@page
@model PrivacyModel
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
ViewData["Title"] = "Privacy RP";
}
<h1>@ViewData["Title"]</h1>
<p>PR Privacy</p>
<h2>
MyRoot:MyParent:MyChildName: @Configuration["MyRoot:MyParent:MyChildName"]
</h2>
In de volgende markeringen wordt de configuratiewaarde weergegeven in een MVC-weergave:
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
ViewData["Title"] = "Privacy MVC";
}
<h1>@ViewData["Title"]</h1>
<p>MVC Use this page to detail your site's privacy policy.</p>
<h2>
MyRoot:MyParent:MyChildName: @Configuration["MyRoot:MyParent:MyChildName"]
</h2>
Zie Configuratie in ASP.NET Core- voor meer informatie
Service-injectie
Een service kan worden geïnjecteerd in een weergave met behulp van de @inject
-instructie.
@using System.Threading.Tasks
@using ViewInjectSample.Model
@using ViewInjectSample.Model.Services
@model IEnumerable<ToDoItem>
@inject StatisticsService StatsService
<!DOCTYPE html>
<html>
<head>
<title>To Do Items</title>
</head>
<body>
<div>
<h1>To Do Items</h1>
<ul>
<li>Total Items: @StatsService.GetCount()</li>
<li>Completed: @StatsService.GetCompletedCount()</li>
<li>Avg. Priority: @StatsService.GetAveragePriority()</li>
</ul>
<table>
<tr>
<th>Name</th>
<th>Priority</th>
<th>Is Done?</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>@item.Name</td>
<td>@item.Priority</td>
<td>@item.IsDone</td>
</tr>
}
</table>
</div>
</body>
</html>
In deze weergave wordt een lijst met ToDoItem
exemplaren weergegeven, samen met een samenvatting met algemene statistieken. De samenvatting wordt gegenereerd uit de geïnjecteerde StatisticsService
. Deze service is geregistreerd voor afhankelijkheidsinjectie in ConfigureServices
in Program.cs
:
using ViewInjectSample.Helpers;
using ViewInjectSample.Infrastructure;
using ViewInjectSample.Interfaces;
using ViewInjectSample.Model.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
builder.Services.AddTransient<IToDoItemRepository, ToDoItemRepository>();
builder.Services.AddTransient<StatisticsService>();
builder.Services.AddTransient<ProfileOptionsService>();
builder.Services.AddTransient<MyHtmlHelper>();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapRazorPages();
app.MapDefaultControllerRoute();
app.Run();
De StatisticsService
voert enkele berekeningen uit op de set ToDoItem
instanties, die het benadert via een opslagplaats.
using System.Linq;
using ViewInjectSample.Interfaces;
namespace ViewInjectSample.Model.Services
{
public class StatisticsService
{
private readonly IToDoItemRepository _toDoItemRepository;
public StatisticsService(IToDoItemRepository toDoItemRepository)
{
_toDoItemRepository = toDoItemRepository;
}
public int GetCount()
{
return _toDoItemRepository.List().Count();
}
public int GetCompletedCount()
{
return _toDoItemRepository.List().Count(x => x.IsDone);
}
public double GetAveragePriority()
{
if (_toDoItemRepository.List().Count() == 0)
{
return 0.0;
}
return _toDoItemRepository.List().Average(x => x.Priority);
}
}
}
De voorbeeldopslagplaats maakt gebruik van een in-memory verzameling. Een in-memory implementatie mag niet worden gebruikt voor grote, extern geopende gegevenssets.
In het voorbeeld worden gegevens van het model weergegeven dat is gebonden aan de weergave en de service die in de weergave is geïnjecteerd:
Opzoekgegevens invullen
Weergave-injectie kan handig zijn om opties in UI-elementen te vullen, zoals vervolgkeuzelijsten. Overweeg een gebruikersprofielformulier met opties voor het opgeven van geslacht, status en andere voorkeuren. Het weergeven van een dergelijk formulier met behulp van een standaardbenadering vereist mogelijk dat de controller of Razor Page het volgende moet doen:
- Services voor gegevenstoegang aanvragen voor elk van de sets met opties.
- Vul een model of
ViewBag
met elke set opties die moeten worden gebonden.
Een alternatieve benadering injecteert diensten rechtstreeks in de weergave om de opties te verkrijgen. Dit minimaliseert de hoeveelheid code die nodig is voor de controller of razor Page, zodat deze logica voor de bouw van weergave-elementen naar de weergave zelf wordt verplaatst. De actie van de controller of de Razor pagina om een bewerkingsformulier voor een profiel weer te geven hoeft alleen het formulier door te geven aan het profielvoorbeeld.
using Microsoft.AspNetCore.Mvc;
using ViewInjectSample.Model;
namespace ViewInjectSample.Controllers;
public class ProfileController : Controller
{
public IActionResult Index()
{
// A real app would up profile based on the user.
var profile = new Profile()
{
Name = "Rick",
FavColor = "Blue",
Gender = "Male",
State = new State("Ohio","OH")
};
return View(profile);
}
}
Het HTML-formulier dat wordt gebruikt om de voorkeuren bij te werken, bevat vervolgkeuzelijsten voor drie van de eigenschappen:
Deze lijsten worden ingevuld door een service die is geïnjecteerd in de weergave:
@using System.Threading.Tasks
@using ViewInjectSample.Model.Services
@model ViewInjectSample.Model.Profile
@inject ProfileOptionsService Options
<!DOCTYPE html>
<html>
<head>
<title>Update Profile</title>
</head>
<body>
<div>
<h1>Update Profile</h1>
Name: @Html.TextBoxFor(m => m.Name)
<br/>
Gender: @Html.DropDownList("Gender",
Options.ListGenders().Select(g =>
new SelectListItem() { Text = g, Value = g }))
<br/>
State: @Html.DropDownListFor(m => m.State!.Code,
Options.ListStates().Select(s =>
new SelectListItem() { Text = s.Name, Value = s.Code}))
<br />
Fav. Color: @Html.DropDownList("FavColor",
Options.ListColors().Select(c =>
new SelectListItem() { Text = c, Value = c }))
</div>
</body>
</html>
De ProfileOptionsService
is een service op gebruikersinterfaceniveau die is ontworpen om alleen de gegevens te bieden die nodig zijn voor dit formulier:
namespace ViewInjectSample.Model.Services;
public class ProfileOptionsService
{
public List<string> ListGenders()
{
// Basic sample
return new List<string>() {"Female", "Male"};
}
public List<State> ListStates()
{
// Add a few states
return new List<State>()
{
new State("Alabama", "AL"),
new State("Alaska", "AK"),
new State("Ohio", "OH")
};
}
public List<string> ListColors()
{
return new List<string>() { "Blue","Green","Red","Yellow" };
}
}
Houd er rekening mee dat een niet-geregistreerd type tijdens runtime een uitzondering genereert omdat de serviceprovider intern wordt opgevraagd via GetRequiredService.
Services overschakelen
Naast het injecteren van nieuwe services, kan deze techniek worden gebruikt om eerder geïnjecteerde services op een pagina te overschrijven. In de onderstaande afbeelding ziet u alle velden die beschikbaar zijn op de pagina die in het eerste voorbeeld wordt gebruikt:
De standaardvelden bevatten Html
, Component
en Url
. Gebruik @inject
om de standaard HTML-helpers te vervangen door een aangepaste versie:
@using System.Threading.Tasks
@using ViewInjectSample.Helpers
@inject MyHtmlHelper Html
<!DOCTYPE html>
<html>
<head>
<title>My Helper</title>
</head>
<body>
<div>
Test: @Html.Value
</div>
</body>
</html>
Zie ook
- Simon Timms Blog: Opzoekgegevens in uw weergave
ASP.NET Core ondersteunt afhankelijkheidsinjectie in weergaven. Dit kan handig zijn voor weergavespecifieke services, zoals lokalisatie of gegevens die alleen nodig zijn voor het invullen van weergave-elementen. Je moet proberen scheiding van verantwoordelijkheden tussen je controllers en weergaven te behouden. De meeste gegevens die worden weergegeven, moeten worden doorgegeven vanuit de controller.
voorbeeldcode weergeven of downloaden (hoe te downloaden)
Configuratie-injectie
appsettings.json
waarden kunnen rechtstreeks in een weergave worden geïnjecteerd.
Voorbeeld van een appsettings.json
-bestand:
{
"root": {
"parent": {
"child": "myvalue"
}
}
}
De syntaxis voor @inject
: @inject <type> <name>
Een voorbeeld met @inject
:
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
string myValue = Configuration["root:parent:child"];
...
}
Service-injectie
Een service kan worden geïnjecteerd in een weergave met behulp van de @inject
-instructie. U kunt @inject
zien als het toevoegen van een eigenschap aan de weergave en het invullen van de eigenschap met behulp van DI.
@using System.Threading.Tasks
@using ViewInjectSample.Model
@using ViewInjectSample.Model.Services
@model IEnumerable<ToDoItem>
@inject StatisticsService StatsService
<!DOCTYPE html>
<html>
<head>
<title>To Do Items</title>
</head>
<body>
<div>
<h1>To Do Items</h1>
<ul>
<li>Total Items: @StatsService.GetCount()</li>
<li>Completed: @StatsService.GetCompletedCount()</li>
<li>Avg. Priority: @StatsService.GetAveragePriority()</li>
</ul>
<table>
<tr>
<th>Name</th>
<th>Priority</th>
<th>Is Done?</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>@item.Name</td>
<td>@item.Priority</td>
<td>@item.IsDone</td>
</tr>
}
</table>
</div>
</body>
</html>
In deze weergave wordt een lijst met ToDoItem
exemplaren weergegeven, samen met een samenvatting met algemene statistieken. De samenvatting wordt ingevuld vanuit de geïnjecteerde StatisticsService
. Deze service is geregistreerd voor afhankelijkheidsinjectie in ConfigureServices
in Startup.cs
:
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
De StatisticsService
voert enkele berekeningen uit op de set ToDoItem
instanties, die via een repository worden benaderd.
using System.Linq;
using ViewInjectSample.Interfaces;
namespace ViewInjectSample.Model.Services
{
public class StatisticsService
{
private readonly IToDoItemRepository _toDoItemRepository;
public StatisticsService(IToDoItemRepository toDoItemRepository)
{
_toDoItemRepository = toDoItemRepository;
}
public int GetCount()
{
return _toDoItemRepository.List().Count();
}
public int GetCompletedCount()
{
return _toDoItemRepository.List().Count(x => x.IsDone);
}
public double GetAveragePriority()
{
if (_toDoItemRepository.List().Count() == 0)
{
return 0.0;
}
return _toDoItemRepository.List().Average(x => x.Priority);
}
}
}
De voorbeeldopslagplaats maakt gebruik van een in-memory verzameling. De hierboven weergegeven implementatie (die op alle gegevens in het geheugen werkt) wordt niet aanbevolen voor grote, extern geopende gegevenssets.
In het voorbeeld worden gegevens van het model weergegeven dat is gebonden aan de weergave en de service die in de weergave is geïnjecteerd:
Opzoekgegevens invullen
Weergave-injectie kan handig zijn om opties in UI-elementen te vullen, zoals vervolgkeuzelijsten. Overweeg een gebruikersprofielformulier met opties voor het opgeven van geslacht, status en andere voorkeuren. Voor het weergeven van een dergelijk formulier met behulp van een standaard MVC-benadering moet de controller gegevenstoegangsservices voor elk van deze sets opties aanvragen en vervolgens een model of ViewBag
vullen met elke set opties die moeten worden gebonden.
Een alternatieve benadering injecteert services rechtstreeks in de weergave om de opties te verkrijgen. Dit minimaliseert de hoeveelheid code die door de controller is vereist, en verplaatst deze logica voor de constructie van weergave-elementen naar de weergave zelf. De controlleractie voor het weergeven van een profielbewerkingsformulier hoeft alleen het profielexemplaar mee te geven aan het formulier.
using Microsoft.AspNetCore.Mvc;
using ViewInjectSample.Model;
namespace ViewInjectSample.Controllers
{
public class ProfileController : Controller
{
[Route("Profile")]
public IActionResult Index()
{
// TODO: look up profile based on logged-in user
var profile = new Profile()
{
Name = "Steve",
FavColor = "Blue",
Gender = "Male",
State = new State("Ohio","OH")
};
return View(profile);
}
}
}
Het HTML-formulier dat wordt gebruikt om deze voorkeuren bij te werken, bevat vervolgkeuzelijsten voor drie van de eigenschappen:
Deze lijsten worden ingevuld door een service die is geïnjecteerd in de weergave:
@using System.Threading.Tasks
@using ViewInjectSample.Model.Services
@model ViewInjectSample.Model.Profile
@inject ProfileOptionsService Options
<!DOCTYPE html>
<html>
<head>
<title>Update Profile</title>
</head>
<body>
<div>
<h1>Update Profile</h1>
Name: @Html.TextBoxFor(m => m.Name)
<br/>
Gender: @Html.DropDownList("Gender",
Options.ListGenders().Select(g =>
new SelectListItem() { Text = g, Value = g }))
<br/>
State: @Html.DropDownListFor(m => m.State.Code,
Options.ListStates().Select(s =>
new SelectListItem() { Text = s.Name, Value = s.Code}))
<br />
Fav. Color: @Html.DropDownList("FavColor",
Options.ListColors().Select(c =>
new SelectListItem() { Text = c, Value = c }))
</div>
</body>
</html>
De ProfileOptionsService
is een service op gebruikersinterfaceniveau die is ontworpen om alleen de gegevens te bieden die nodig zijn voor dit formulier:
using System.Collections.Generic;
namespace ViewInjectSample.Model.Services
{
public class ProfileOptionsService
{
public List<string> ListGenders()
{
// keeping this simple
return new List<string>() {"Female", "Male"};
}
public List<State> ListStates()
{
// a few states from USA
return new List<State>()
{
new State("Alabama", "AL"),
new State("Alaska", "AK"),
new State("Ohio", "OH")
};
}
public List<string> ListColors()
{
return new List<string>() { "Blue","Green","Red","Yellow" };
}
}
}
Belangrijk
Vergeet niet om de typen die u via afhankelijkheidsinjectie aanvraagt, te registreren in Startup.ConfigureServices
. Een niet-geregistreerd type genereert tijdens runtime een uitzondering omdat de serviceprovider intern wordt opgevraagd via GetRequiredService.
Services overschrijven
Naast het injecteren van nieuwe services, kan deze techniek ook worden gebruikt om eerder geïnjecteerde services op een pagina te overschrijven. In de onderstaande afbeelding ziet u alle velden die beschikbaar zijn op de pagina die in het eerste voorbeeld wordt gebruikt:
Zoals u kunt zien, bevatten de standaardvelden Html
, Component
en Url
(evenals de StatsService
die we hebben geïnjecteerd). Als u bijvoorbeeld de standaard HTML Helpers wilt vervangen door uw eigen HTML-helpers, kunt u dit eenvoudig doen met behulp van @inject
:
@using System.Threading.Tasks
@using ViewInjectSample.Helpers
@inject MyHtmlHelper Html
<!DOCTYPE html>
<html>
<head>
<title>My Helper</title>
</head>
<body>
<div>
Test: @Html.Value
</div>
</body>
</html>
Als u bestaande services wilt uitbreiden, kunt u deze techniek gewoon gebruiken tijdens het overnemen van of verpakken van de bestaande implementatie met uw eigen implementatie.
Zie ook
- Simon Timms Blog: Gegevens opzoeken in uw weergave