Injeksi dependensi ke dalam tampilan di ASP.NET Core
ASP.NET Core mendukung injeksi dependensi ke dalam tampilan. Ini dapat berguna untuk layanan khusus tampilan, seperti pelokalan atau data yang diperlukan hanya untuk mengisi elemen tampilan. Sebagian besar tampilan tampilan data harus diteruskan dari pengontrol.
Melihat atau mengunduh kode sampel (cara mengunduh)
Injeksi konfigurasi
Nilai dalam file pengaturan, seperti appsettings.json
dan appsettings.Development.json
, dapat disuntikkan ke dalam tampilan. appsettings.Development.json
Pertimbangkan dari kode sampel:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"MyRoot": {
"MyParent": {
"MyChildName": "Joe"
}
}
}
Markup berikut menampilkan nilai konfigurasi dalam Razor tampilan Halaman:
@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>
Markup berikut menampilkan nilai konfigurasi dalam tampilan 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>
Untuk informasi selengkapnya, lihat Konfigurasi di ASP.NET Core
Injeksi layanan
Layanan dapat disuntikkan ke dalam tampilan menggunakan direktif @inject
.
@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>
Tampilan ini menampilkan daftar ToDoItem
instans, bersama dengan ringkasan yang menunjukkan statistik keseluruhan. Ringkasan diisi dari yang disuntikkan StatisticsService
. Layanan ini terdaftar untuk injeksi dependensi di ConfigureServices
: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();
StatisticsService
melakukan beberapa perhitungan pada kumpulan ToDoItem
instans, yang diaksesnya melalui repositori:
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);
}
}
}
Repositori sampel menggunakan koleksi dalam memori. Implementasi dalam memori tidak boleh digunakan untuk himpunan data besar yang diakses dari jarak jauh.
Sampel menampilkan data dari model yang terikat ke tampilan dan layanan yang disuntikkan ke dalam tampilan:
Mengisi Data Pencarian
Injeksi tampilan dapat berguna untuk mengisi opsi dalam elemen UI, seperti daftar dropdown. Pertimbangkan formulir profil pengguna yang menyertakan opsi untuk menentukan jenis kelamin, status, dan preferensi lainnya. Merender formulir seperti itu menggunakan pendekatan standar mungkin memerlukan pengontrol atau Razor Halaman untuk:
- Meminta layanan akses data untuk setiap set opsi.
- Isi model atau
ViewBag
dengan setiap set opsi yang akan terikat.
Pendekatan alternatif menyuntikkan layanan langsung ke tampilan untuk mendapatkan opsi. Ini meminimalkan jumlah kode yang diperlukan oleh pengontrol atau razor Halaman, memindahkan logika konstruksi elemen tampilan ini ke tampilan itu sendiri. Tindakan pengontrol atau Razor Halaman untuk menampilkan formulir pengeditan profil hanya perlu meneruskan formulir instans profil:
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);
}
}
Formulir HTML yang digunakan untuk memperbarui preferensi menyertakan daftar dropdown untuk tiga properti:
Daftar ini diisi oleh layanan yang telah disuntikkan ke dalam tampilan:
@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>
ProfileOptionsService
adalah layanan tingkat UI yang dirancang untuk menyediakan hanya data yang diperlukan untuk formulir ini:
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" };
}
}
Perhatikan jenis yang tidak terdaftar melempar pengecualian saat runtime karena penyedia layanan secara internal dikueri melalui GetRequiredService.
Layanan Penggantian
Selain menyuntikkan layanan baru, teknik ini dapat digunakan untuk mengambil alih layanan yang sebelumnya disuntikkan pada halaman. Gambar di bawah ini menunjukkan semua bidang yang tersedia di halaman yang digunakan dalam contoh pertama:
Bidang default mencakup Html
, Component
, dan Url
. Untuk mengganti Pembantu HTML default dengan versi kustom, gunakan @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>
Lihat Juga
- Blog Simon Timms: Mendapatkan Data Pencarian Ke Dalam Tampilan Anda
ASP.NET Core mendukung injeksi dependensi ke dalam tampilan. Ini dapat berguna untuk layanan khusus tampilan, seperti pelokalan atau data yang diperlukan hanya untuk mengisi elemen tampilan. Anda harus mencoba mempertahankan pemisahan kekhawatiran antara pengontrol dan tampilan Anda. Sebagian besar data yang ditampilkan tampilan Anda harus diteruskan dari pengontrol.
Melihat atau mengunduh kode sampel (cara mengunduh)
Injeksi konfigurasi
appsettings.json
nilai dapat disuntikkan langsung ke dalam tampilan.
appsettings.json
Contoh file:
{
"root": {
"parent": {
"child": "myvalue"
}
}
}
Sintaks untuk @inject
: @inject <type> <name>
Contoh menggunakan @inject
:
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
string myValue = Configuration["root:parent:child"];
...
}
Injeksi layanan
Layanan dapat disuntikkan ke dalam tampilan menggunakan direktif @inject
. Anda dapat menganggap @inject
sebagai menambahkan properti ke tampilan, dan mengisi properti menggunakan 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>
Tampilan ini menampilkan daftar ToDoItem
instans, bersama dengan ringkasan yang menunjukkan statistik keseluruhan. Ringkasan diisi dari yang disuntikkan StatisticsService
. Layanan ini terdaftar untuk injeksi dependensi di ConfigureServices
: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();
StatisticsService
melakukan beberapa perhitungan pada kumpulan ToDoItem
instans, yang diaksesnya melalui repositori:
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);
}
}
}
Repositori sampel menggunakan koleksi dalam memori. Implementasi yang ditunjukkan di atas (yang beroperasi pada semua data dalam memori) tidak disarankan untuk himpunan data besar yang diakses dari jarak jauh.
Sampel menampilkan data dari model yang terikat ke tampilan dan layanan yang disuntikkan ke dalam tampilan:
Mengisi Data Pencarian
Injeksi tampilan dapat berguna untuk mengisi opsi dalam elemen UI, seperti daftar dropdown. Pertimbangkan formulir profil pengguna yang menyertakan opsi untuk menentukan jenis kelamin, status, dan preferensi lainnya. Merender formulir seperti itu menggunakan pendekatan MVC standar akan mengharuskan pengontrol untuk meminta layanan akses data untuk setiap set opsi ini, lalu mengisi model atau ViewBag
dengan setiap set opsi untuk terikat.
Pendekatan alternatif menyuntikkan layanan langsung ke tampilan untuk mendapatkan opsi. Ini meminimalkan jumlah kode yang diperlukan oleh pengontrol, memindahkan logika konstruksi elemen tampilan ini ke dalam tampilan itu sendiri. Tindakan pengontrol untuk menampilkan formulir pengeditan profil hanya perlu meneruskan formulir instans profil:
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);
}
}
}
Formulir HTML yang digunakan untuk memperbarui preferensi ini menyertakan daftar dropdown untuk tiga properti:
Daftar ini diisi oleh layanan yang telah disuntikkan ke dalam tampilan:
@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>
ProfileOptionsService
adalah layanan tingkat UI yang dirancang untuk menyediakan hanya data yang diperlukan untuk formulir ini:
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" };
}
}
}
Penting
Jangan lupa untuk mendaftarkan jenis yang Anda minta melalui injeksi dependensi di Startup.ConfigureServices
. Jenis yang tidak terdaftar melempar pengecualian saat runtime karena penyedia layanan secara internal dikueri melalui GetRequiredService.
Layanan Penggantian
Selain menyuntikkan layanan baru, teknik ini juga dapat digunakan untuk mengambil alih layanan yang sebelumnya disuntikkan pada halaman. Gambar di bawah ini menunjukkan semua bidang yang tersedia di halaman yang digunakan dalam contoh pertama:
Seperti yang Anda lihat, bidang default mencakup Html
, , Component
dan Url
(serta StatsService
yang kami suntikkan). Jika misalnya Anda ingin mengganti Pembantu HTML default dengan pembantu HTML Anda sendiri, Anda dapat dengan mudah melakukannya menggunakan @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>
Jika Anda ingin memperluas layanan yang ada, Anda cukup menggunakan teknik ini sambil mewarisi dari atau membungkus implementasi yang ada dengan milik Anda sendiri.
Lihat Juga
- Blog Simon Timms: Mendapatkan Data Pencarian Ke Dalam Tampilan Anda
ASP.NET Core