ASP.NET Core의 보기에 종속성 주입Dependency injection into views in ASP.NET Core

작성자: Steve SmithBy Steve Smith

ASP.NET Core는 보기에 종속성 주입을 지원합니다.ASP.NET Core supports dependency injection into views. 보기 요소를 채우는 데만 필요한 지역화 또는 데이터 같은 보기 관련 서비스에 유용합니다.This can be useful for view-specific services, such as localization or data required only for populating view elements. 컨트롤러와 보기 사이에 문제를 분리해야 합니다.You should try to maintain separation of concerns between your controllers and views. 보기에서 표시하는 대부분의 데이터는 컨트롤러에서 전달되어야 합니다.Most of the data your views display should be passed in from the controller.

예제 코드 살펴보기 및 다운로드(다운로드 방법)View or download sample code (how to download)

간단한 예제A Simple Example

@inject 지시문을 사용하여 보기에 서비스를 삽입할 수 있습니다.You can inject a service into a view using the @inject directive. @inject를 보기에 속성을 추가하고 DI를 사용하여 속성을 채우는 것으로 생각하셔도 좋습니다.You can think of @inject as adding a property to your view, and populating the property using DI.

@inject에 대한 구문: @inject <type> <name>The syntax for @inject: @inject <type> <name>

실제로 작동하는 @inject 예제:An example of @inject in action:

@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 인스턴스 목록을 표시합니다.This view displays a list of ToDoItem instances, along with a summary showing overall statistics. 요약 정보는 주입된 StatisticsService에서 채워집니다.The summary is populated from the injected StatisticsService. 이 서비스는 Startup.csConfigureServices에서 종속성 주입을 위해 등록됩니다.This service is registered for dependency injection in ConfigureServices in Startup.cs:

// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddTransient<IToDoItemRepository, ToDoItemRepository>();
    services.AddTransient<StatisticsService>();
    services.AddTransient<ProfileOptionsService>();

StatisticsService는 리포지토리를 통해 액세스되는 ToDoItem 인스턴스 집합에서 몇 가지 계산을 수행합니다.The StatisticsService performs some calculations on the set of ToDoItem instances, which it accesses via a repository:

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

샘플 리포지토리는 메모리 내 컬렉션을 사용합니다.The sample repository uses an in-memory collection. 위에서 보여드린 구현은 메모리 내 모든 데이터에서 작동하므로 원격으로 액세스되는 대규모 데이터 집합에는 권장하지 않습니다.The implementation shown above (which operates on all of the data in memory) isn't recommended for large, remotely accessed data sets.

이 샘플은 보기에 바인딩된 모델과 보기에 주입된 서비스의 데이터를 표시합니다.The sample displays data from the model bound to the view and the service injected into the view:

총 항목, 완료된 항목, 평균 우선 순위, 작업 목록을 해당 우선 순위 수준 및 작업 완료를 나타내는 부울 값과 함께 나열하는 할 일 보기입니다.

조회 데이터 채우기Populating Lookup Data

보기 주입은 드롭다운 목록 같은 UI 요소의 옵션을 채우는 데 유용할 수 있습니다.View injection can be useful to populate options in UI elements, such as dropdown lists. 성별, 상태 및 기타 기본 설정을 지정하는 옵션이 포함된 사용자 프로필 양식을 고려해 보세요.Consider a user profile form that includes options for specifying gender, state, and other preferences. 표준 MVC 방식을 사용하는 양식 같은 렌더링의 경우 컨트롤러에서 이러한 각 옵션 집합에 대한 데이터 액세스 서비스를 요청한 후 모델 또는 ViewBag을 바인딩할 각 옵션 집합으로 채워야 합니다.Rendering such a form using a standard MVC approach would require the controller to request data access services for each of these sets of options, and then populate a model or ViewBag with each set of options to be bound.

다른 방법은 서비스를 보기에 직접 주입하여 옵션을 가져오는 것입니다.An alternative approach injects services directly into the view to obtain the options. 이 방법은 컨트롤러에 필요한 코드 양을 최소화하고, 이 보기 요소 생성 논리를 보기 자체로 이동합니다.This minimizes the amount of code required by the controller, moving this view element construction logic into the view itself. 프로필 편집 양식을 표시하는 컨트롤러 작업은 양식을 프로필 인스턴스에 전달하기만 하면 됩니다.The controller action to display a profile editing form only needs to pass the form the profile instance:

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 양식으로는 다음과 같은 세 가지 속성에 대한 드롭다운 목록이 포함됩니다.The HTML form used to update these preferences includes dropdown lists for three of the properties:

이름, 성별, 상태 및 좋아하는 색을 입력할 수 있는 양식을 제공하는 프로필 업데이트 보기.

이러한 목록은 보기에 주입된 서비스로 채워집니다.These lists are populated by a service that has been injected into the view:

@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 수준 서비스입니다.The ProfileOptionsService is a UI-level service designed to provide just the data needed for this form:

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.csConfigureServices 메서드에서 종속성 주입을 통해 요청할 유형을 등록하는 것을 잊지 마세요.Don't forget to register types you will request through dependency injection in the ConfigureServices method in Startup.cs.

서비스 재정의Overriding Services

새 서비스 주입 외에도, 이 기술은 페이지에서 이전에 주입된 서비스를 재정의하는 데 사용할 수 있습니다.In addition to injecting new services, this technique can also be used to override previously injected services on a page. 아래 그림은 첫 번째 예에서 사용된 페이지에서 사용 가능한 모든 필드를 보여줍니다.The figure below shows all of the fields available on the page used in the first example:

입력된 @ 기호에서 Html, 구성 요소, StatsService 및 Url 필드를 나열하는 Intellisense 상황에 맞는 메뉴

보시는 것처럼 기본 필드로 Html, ComponentUrl(그리고 우리가 주입한 StatsService)이 있습니다.As you can see, the default fields include Html, Component, and Url (as well as the StatsService that we injected). 예를 들어 기본 HTML 도우미를 개발자 고유의 도우미로 바꾸려면 간단하게 @inject를 사용하면 됩니다.If for instance you wanted to replace the default HTML Helpers with your own, you could easily do so using @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>

기존 서비스를 확장하려는 경우 간단하게 이 기술을 사용하여 기존 구현에서 상속하거나 기존 구현을 개발자 고유의 구현으로 래핑하면 됩니다.If you want to extend existing services, you can simply use this technique while inheriting from or wrapping the existing implementation with your own.

참고 항목See Also