Wstrzykiwanie zależności do widoków w programie ASP.NET Core
ASP.NET Core obsługuje wstrzykiwanie zależności do widoków. Może to być przydatne w przypadku usług specyficznych dla widoku, takich jak lokalizacja lub dane wymagane tylko do wypełniania elementów widoku. Większość wyświetlanych widoków danych powinna zostać przekazana z kontrolera.
Wyświetl lub pobierz przykładowy kod (jak pobrać)
Iniekcja konfiguracji
Wartości w plikach ustawień, takich jak appsettings.json
i appsettings.Development.json
, można wstrzykiwać do widoku. Rozważ użycie appsettings.Development.json
kodu przykładowego:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"MyRoot": {
"MyParent": {
"MyChildName": "Joe"
}
}
}
Poniższy znacznik wyświetla wartość konfiguracji w Razor widoku Strony:
@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>
Poniższy znacznik wyświetla wartość konfiguracji w widoku MVC:
@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>
Aby uzyskać więcej informacji, zobacz Configuration in ASP.NET Core (Konfiguracja w programie ASP.NET Core)
Wstrzykiwanie usługi
Usługę można wstrzyknąć do widoku przy użyciu @inject
dyrektywy .
@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>
Ten widok zawiera listę ToDoItem
wystąpień wraz z podsumowaniem przedstawiającym ogólne statystyki. Podsumowanie jest wypełniane ze wstrzykniętego StatisticsService
elementu . Ta usługa jest zarejestrowana do wstrzykiwania zależności w programie ConfigureServices
w programie 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();
Funkcja StatisticsService
wykonuje pewne obliczenia na zestawie ToDoItem
wystąpień, do których uzyskuje dostęp za pośrednictwem repozytorium:
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);
}
}
}
Przykładowe repozytorium używa kolekcji w pamięci. Implementacja w pamięci nie powinna być używana w przypadku dużych, zdalnych zestawów danych.
Przykład wyświetla dane z modelu powiązanego z widokiem i usługą wstrzykniętą do widoku:
Wypełnianie danych odnośników
Iniekcja widoku może być przydatna do wypełniania opcji w elementach interfejsu użytkownika, takich jak listy rozwijane. Rozważ formularz profilu użytkownika zawierający opcje określania płci, stanu i innych preferencji. Renderowanie takiego formularza przy użyciu standardowego podejścia może wymagać, aby kontroler lub Razor strona:
- Żądanie usług dostępu do danych dla każdego zestawu opcji.
- Wypełnij model lub
ViewBag
przy użyciu każdego zestawu opcji, które mają być powiązane.
Alternatywne podejście wprowadza usługi bezpośrednio do widoku w celu uzyskania opcji. Minimalizuje to ilość kodu wymaganego przez kontroler lub razor stronę, przenosząc logikę budowy tego elementu widoku do samego widoku. Akcja kontrolera lub Razor strona, aby wyświetlić formularz edycji profilu, musi przekazać tylko formularz wystąpienia profilu:
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);
}
}
Formularz HTML używany do aktualizowania preferencji zawiera listy rozwijane dla trzech właściwości:
Te listy są wypełniane przez usługę, która została wstrzyknięta do widoku:
@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>
Jest ProfileOptionsService
to usługa na poziomie interfejsu użytkownika zaprojektowana tak, aby dostarczać tylko dane potrzebne do tego formularza:
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" };
}
}
Zwróć uwagę, że typ wyrejestrowany zgłasza wyjątek w czasie wykonywania, ponieważ dostawca usług jest wewnętrznie odpytywany za pośrednictwem polecenia GetRequiredService.
Zastępowanie usług
Oprócz wstrzykiwania nowych usług ta technika może służyć do zastępowania wcześniej wstrzykiwanych usług na stronie. Na poniższej ilustracji przedstawiono wszystkie pola dostępne na stronie użyte w pierwszym przykładzie:
Pola domyślne obejmują Html
, Component
i Url
. Aby zastąpić domyślnych pomocników HTML niestandardową wersją, użyj polecenia @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>
Zobacz też
- Simon Timms Blog: Pobieranie danych odnośników do widoku
ASP.NET Core obsługuje wstrzykiwanie zależności do widoków. Może to być przydatne w przypadku usług specyficznych dla widoku, takich jak lokalizacja lub dane wymagane tylko do wypełniania elementów widoku. Należy starać się zachować separację problemów między kontrolerami i poglądami . Większość danych wyświetlanych widoków powinna zostać przekazana z kontrolera.
Wyświetl lub pobierz przykładowy kod (jak pobrać)
Iniekcja konfiguracji
appsettings.json
wartości można wstrzykiwać bezpośrednio do widoku.
appsettings.json
Przykład pliku:
{
"root": {
"parent": {
"child": "myvalue"
}
}
}
Składnia dla elementu @inject
: @inject <type> <name>
Przykład z użyciem polecenia @inject
:
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
string myValue = Configuration["root:parent:child"];
...
}
Wstrzykiwanie usługi
Usługę można wstrzyknąć do widoku przy użyciu @inject
dyrektywy . Możesz traktować @inject
jako dodawanie właściwości do widoku i wypełnianie właściwości przy użyciu 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>
Ten widok zawiera listę ToDoItem
wystąpień wraz z podsumowaniem przedstawiającym ogólne statystyki. Podsumowanie jest wypełniane ze wstrzykniętego StatisticsService
elementu . Ta usługa jest zarejestrowana do wstrzykiwania zależności w programie ConfigureServices
w programie 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();
Funkcja StatisticsService
wykonuje pewne obliczenia na zestawie ToDoItem
wystąpień, do których uzyskuje dostęp za pośrednictwem repozytorium:
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);
}
}
}
Przykładowe repozytorium używa kolekcji w pamięci. Implementacja pokazana powyżej (która działa na wszystkich danych w pamięci) nie jest zalecana w przypadku dużych, zdalnych zestawów danych.
Przykład wyświetla dane z modelu powiązanego z widokiem i usługą wstrzykniętą do widoku:
Wypełnianie danych odnośników
Iniekcja widoku może być przydatna do wypełniania opcji w elementach interfejsu użytkownika, takich jak listy rozwijane. Rozważ formularz profilu użytkownika zawierający opcje określania płci, stanu i innych preferencji. Renderowanie takiego formularza przy użyciu standardowego podejścia MVC wymagałoby od kontrolera żądania usług dostępu do danych dla każdego z tych zestawów opcji, a następnie wypełnienia modelu lub ViewBag
każdego zestawu opcji, które mają być powiązane.
Alternatywne podejście wprowadza usługi bezpośrednio do widoku w celu uzyskania opcji. Minimalizuje to ilość kodu wymaganego przez kontroler, przenosząc logikę budowy tego elementu widoku do samego widoku. Akcja kontrolera w celu wyświetlenia formularza edycji profilu musi jedynie przekazać formularz wystąpienia profilu:
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);
}
}
}
Formularz HTML używany do aktualizowania tych preferencji zawiera listy rozwijane dla trzech właściwości:
Te listy są wypełniane przez usługę, która została wstrzyknięta do widoku:
@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>
Jest ProfileOptionsService
to usługa na poziomie interfejsu użytkownika zaprojektowana tak, aby dostarczać tylko dane potrzebne do tego formularza:
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" };
}
}
}
Ważne
Nie zapomnij zarejestrować typów, których żądasz za pomocą iniekcji zależności w programie Startup.ConfigureServices
. Typ wyrejestrowany zgłasza wyjątek w czasie wykonywania, ponieważ dostawca usług jest wewnętrznie odpytywany za pośrednictwem metody GetRequiredService.
Zastępowanie usług
Oprócz wstrzykiwania nowych usług ta technika może również służyć do zastępowania wcześniej wstrzykiwanych usług na stronie. Na poniższej ilustracji przedstawiono wszystkie pola dostępne na stronie użyte w pierwszym przykładzie:
Jak widać, pola domyślne obejmują Html
, Component
i Url
(a także StatsService
wprowadzone przez nas pola). Jeśli na przykład chcesz zastąpić domyślnych pomocników HTML własnymi, możesz to łatwo zrobić przy użyciu polecenia @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>
Jeśli chcesz rozszerzyć istniejące usługi, możesz po prostu użyć tej techniki podczas dziedziczenia z lub opakowywania istniejącej implementacji własnymi.
Zobacz też
- Simon Timms Blog: Pobieranie danych odnośników do widoku