ASP.NET Core의 보기에 종속성 주입
ASP.NET Core는 보기에 대한 종속성 주입을 지원합니다. 이는 보기 요소를 채우는 데만 필요한 지역화 또는 데이터 같은 보기 관련 서비스에 유용합니다. 대부분의 데이터 뷰 디스플레이는 컨트롤러에서 전달되어야 합니다.
구성 주입
설정 파일의 값(예: appsettings.json
및 appsettings.Development.json
)을 보기에 삽입할 수 있습니다. appsettings.Development.json
샘플 코드에서 다음을 고려합니다.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"MyRoot": {
"MyParent": {
"MyChildName": "Joe"
}
}
}
다음 태그는 페이지 보기에 Razor 구성 값을 표시합니다.
@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>
다음 태그는 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>
자세한 내용은 ASP.NET Core의 구성을 참조하세요.
서비스 주입
@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>
이 보기는 전체 통계를 보여주는 요약 정보와 함께 ToDoItem
인스턴스 목록을 표시합니다. 요약 정보는 주입된 StatisticsService
에서 채워집니다. 이 서비스는 다음에서 종속성 주입을 위해 등록됩니다.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
는 리포지토리를 통해 액세스되는 ToDoItem
인스턴스 집합에서 몇 가지 계산을 수행합니다.
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);
}
}
}
예제 리포지토리는 메모리 내 컬렉션을 사용합니다. 메모리 내 구현은 원격으로 액세스하는 대규모 데이터 집합에 사용하면 안 됩니다.
이 예제는 보기에 바인딩된 모델과 보기에 주입된 서비스의 데이터를 표시합니다.
조회 데이터 채우기
보기 주입은 드롭다운 목록 같은 UI 요소의 옵션을 채우는 데 유용합니다. 성별, 상태 및 기타 기본 설정을 지정하는 옵션이 포함된 사용자 프로필 양식을 고려해보세요. 표준 접근 방식을 사용하여 이러한 양식을 렌더링하려면 컨트롤러 또는 Razor 페이지가 다음을 수행해야 할 수 있습니다.
- 각 옵션 집합에 대한 데이터 액세스 서비스를 요청합니다.
- 모델을 채웁다 또는
ViewBag
바인딩할 각 옵션 집합을 사용합니다.
다른 방법은 서비스를 보기에 직접 주입하여 옵션을 가져오는 것입니다. 이렇게 하면 컨트롤러 또는 razor Page에 필요한 코드 양이 최소화되어 이 뷰 요소 생성 논리를 보기 자체로 이동합니다. 프로필 편집 양식을 표시하는 컨트롤러 작업 또는 Razor 페이지는 프로필 인스턴스 양식을 전달하기만 하면됩니다.
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);
}
}
기본 설정을 업데이트하는 데 사용되는 HTML 양식에는 다음 세 가지 속성에 대한 드롭다운 목록이 포함됩니다.
이러한 목록은 보기에 주입된 서비스에 의해서 채워집니다.
@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
는 이 양식에 필요한 데이터만 제공하도록 설계된 UI 수준 서비스입니다.
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" };
}
}
등록되지 않은 형식은 서비스 공급자가 내부적으로 GetRequiredService쿼리되기 때문에 런타임에 예외를 throw합니다.
서비스 재정의
이 기술은 새 서비스를 삽입하는 것 외에도 페이지에서 이전에 삽입된 서비스를 재정의하는 데 사용할 수 있습니다. 아래 그림은 첫 번째 예에서 사용된 페이지에서 사용 가능한 모든 필드를 보여줍니다.
기본 필드에는 , 및 Url
.가 Component
포함됩니다Html
. 기본 HTML 도우미를 사용자 지정 버전으로 바꾸려면 다음을 사용합니다 @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>
참고 항목
- Simon Timms 블로그: 보기로 조회 데이터 가져오기
ASP.NET Core는 보기에 대한 종속성 주입을 지원합니다. 이는 보기 요소를 채우는 데만 필요한 지역화 또는 데이터 같은 보기 관련 서비스에 유용합니다. 컨트롤러와 보기 간에 문제를 분리해야 합니다. 보기에서 표시하는 대부분의 데이터는 컨트롤러에서 전달되어야 합니다.
구성 주입
appsettings.json
값을 보기에 직접 주입할 수 있습니다.
appsettings.json
파일의 예:
{
"root": {
"parent": {
"child": "myvalue"
}
}
}
@inject
에 대한 구문: @inject <type> <name>
@inject
를 사용하는 예제:
@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
string myValue = Configuration["root:parent:child"];
...
}
서비스 주입
@inject
지시문을 사용하여 서비스를 보기에 주입할 수 있습니다. @inject
를 보기에 속성을 추가하고 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>
이 보기는 전체 통계를 보여주는 요약 정보와 함께 ToDoItem
인스턴스 목록을 표시합니다. 요약 정보는 주입된 StatisticsService
에서 채워집니다. 이 서비스는 다음에서 종속성 주입을 위해 등록됩니다.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
는 리포지토리를 통해 액세스되는 ToDoItem
인스턴스 집합에서 몇 가지 계산을 수행합니다.
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);
}
}
}
예제 리포지토리는 메모리 내 컬렉션을 사용합니다. 위에서 살펴본 구현은 메모리 내의 모든 데이터를 대상으로 작동하므로 원격으로 액세스되는 대규모 데이터 집합에는 권장하지 않습니다.
이 예제는 보기에 바인딩된 모델과 보기에 주입된 서비스의 데이터를 표시합니다.
조회 데이터 채우기
보기 주입은 드롭다운 목록 같은 UI 요소의 옵션을 채우는 데 유용합니다. 성별, 상태 및 기타 기본 설정을 지정하는 옵션이 포함된 사용자 프로필 양식을 고려해보세요. 표준 MVC 방식을 사용하여 이러한 양식을 렌더링하려면 컨트롤러에서 이러한 각 옵션 집합에 대한 데이터 액세스 서비스를 요청한 후 모델 또는 ViewBag
을 바인딩할 각 옵션 집합으로 채워야합니다.
다른 방법은 서비스를 보기에 직접 주입하여 옵션을 가져오는 것입니다. 이 방법은 컨트롤러에 필요한 코드 양을 최소화하고, 보기 요소 생성 논리를 보기 자체로 이동합니다. 프로필 편집 양식을 표시하는 컨트롤러 작업은 프로필 인스턴스 양식만 전달하면 됩니다.
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);
}
}
}
이러한 기본 설정을 수정하기 위한 HTML 양식으로는 세 가지 속성에 대한 드롭다운 목록을 포함합니다.
이러한 목록은 보기에 주입된 서비스에 의해서 채워집니다.
@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
는 이 양식에 필요한 데이터만 제공하도록 설계된 UI 수준 서비스입니다.
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" };
}
}
}
중요
Startup.ConfigureServices
에서 종속성 주입을 통해 요청할 형식을 등록하는 것을 잊지 마세요. 등록되지 않은 형식은 서비스 공급자가 내부적으로 GetRequiredService쿼리되기 때문에 런타임에 예외를 throw합니다.
서비스 재정의
새 서비스 주입 외에도, 이 기술은 페이지에서 이전에 주입된 서비스를 재정의하는 데 사용할 수도 있습니다. 아래 그림은 첫 번째 예에서 사용된 페이지에서 사용 가능한 모든 필드를 보여줍니다.
볼 수 있는 것처럼 기본 필드에는 Html
, Component
및 Url
(그리고 우리가 주입한 StatsService
)이 포함됩니다. 예를 들어 기본 HTML 도우미를 개발자 고유의 도우미로 바꾸려면 간단하게 @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>
기존 서비스를 확장하려는 경우 간단하게 이 기술을 사용하여 기존 구현에서 상속하거나 기존 구현을 개발자 고유의 구현으로 래핑하면 됩니다.
참고 항목
- Simon Timms 블로그: 보기로 조회 데이터 가져오기