다음을 통해 공유


보기 마스터 페이지에 데이터 전달(C#)

작성자: Microsoft

PDF 다운로드

이 자습서의 목표는 컨트롤러에서 보기 master 페이지로 데이터를 전달하는 방법을 설명하는 것입니다. 뷰 master 페이지에 데이터를 전달하기 위한 두 가지 전략을 살펴봅니다. 먼저 유지 관리가 어려운 애플리케이션을 만드는 쉬운 솔루션에 대해 설명합니다. 다음으로, 좀 더 초기 작업이 필요하지만 훨씬 더 유지 관리 가능한 애플리케이션을 만드는 훨씬 더 나은 솔루션을 살펴봅니다.

마스터 페이지 보기에 데이터 전달

이 자습서의 목표는 컨트롤러에서 보기 master 페이지로 데이터를 전달하는 방법을 설명하는 것입니다. 뷰 master 페이지에 데이터를 전달하기 위한 두 가지 전략을 살펴봅니다. 먼저 유지 관리가 어려운 애플리케이션을 만드는 쉬운 솔루션에 대해 설명합니다. 다음으로, 좀 더 초기 작업이 필요하지만 훨씬 더 유지 관리 가능한 애플리케이션을 만드는 훨씬 더 나은 솔루션을 살펴봅니다.

문제

동영상 데이터베이스 애플리케이션을 빌드하고 애플리케이션의 모든 페이지에 영화 범주 목록을 표시하려는 경우를 상상해 보세요(그림 1 참조). 또한 영화 범주 목록이 데이터베이스 테이블에 저장되어 있다고 상상해 보세요. 이 경우 데이터베이스에서 범주를 검색하고 보기 master 페이지 내에서 영화 범주 목록을 렌더링하는 것이 좋습니다.

보기 master 페이지에 영화 범주 표시

그림 01: 보기 master 페이지에 동영상 범주 표시(전체 크기 이미지를 보려면 클릭)

다음은 문제입니다. master 페이지에서 영화 범주 목록을 검색하려면 어떻게 해야 합니까? master 페이지에서 모델 클래스의 메서드를 직접 호출하려고 합니다. 즉, 데이터베이스에서 데이터를 검색하는 코드를 master 페이지에 포함하려는 경우입니다. 그러나 MVC 컨트롤러를 우회하여 데이터베이스에 액세스하는 것은 MVC 애플리케이션을 빌드할 때의 주요 이점 중 하나인 클린 문제 분리를 위반합니다.

MVC 애플리케이션에서는 MVC 뷰와 MVC 모델 간의 모든 상호 작용을 MVC 컨트롤러에서 처리하려고 합니다. 이러한 문제를 분리하면 유지 관리가 가능하고 적응 가능하며 테스트 가능한 애플리케이션이 됩니다.

MVC 애플리케이션에서 보기 master 페이지를 포함하여 뷰에 전달된 모든 데이터는 컨트롤러 작업을 통해 뷰에 전달되어야 합니다. 또한 뷰 데이터를 활용하여 데이터를 전달해야 합니다. 이 자습서의 나머지 부분에서는 보기 master 페이지에 보기 데이터를 전달하는 두 가지 방법을 살펴봅니다.

간단한 솔루션

컨트롤러에서 보기 master 페이지로 보기 데이터를 전달하는 가장 간단한 솔루션부터 시작해 보겠습니다. 가장 간단한 솔루션은 각 컨트롤러 작업에서 master 페이지의 보기 데이터를 전달하는 것입니다.

목록 1에서 컨트롤러를 고려합니다. 및 Details()라는 Index() 두 작업을 노출합니다. Action 메서드는 Index() Movies 데이터베이스 테이블의 모든 동영상을 반환합니다. action 메서드는 Details() 특정 영화 범주의 모든 동영상을 반환합니다.

목록 1 – Controllers\HomeController.cs

using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
     [HandleError]
     public class HomeController : Controller
     {
          private MovieDataContext _dataContext = new MovieDataContext();

          /// <summary>

          /// Show list of all movies
          /// </summary>
          public ActionResult Index()
          {
               ViewData["categories"] = from c in _dataContext.MovieCategories 
                         select c;
               ViewData["movies"] = from m in _dataContext.Movies 
                         select m;
               return View();
          }

          /// <summary>
          /// Show list of movies in a category
          /// </summary>

          public ActionResult Details(int id)
          {
               ViewData["categories"] = from c in _dataContext.MovieCategories 
                         select c;
               ViewData["movies"] = from m in _dataContext.Movies 
                         where m.CategoryId == id
                         select m;
               return View();
          }
     }
}

Index() 및 Details() 작업 둘 다 데이터를 보기 위해 두 개의 항목을 추가합니다. Index() 작업은 범주와 영화라는 두 개의 키를 추가합니다. 범주 키는 보기 master 페이지에 표시되는 영화 범주 목록을 나타냅니다. 영화 키는 인덱스 보기 페이지에 표시되는 영화 목록을 나타냅니다.

Details() 작업은 범주와 영화라는 두 개의 키도 추가합니다. 범주 키는 다시 한 번 보기 master 페이지에 표시되는 영화 범주 목록을 나타냅니다. 동영상 키는 세부 정보 보기 페이지에 표시되는 특정 범주의 영화 목록을 나타냅니다(그림 2 참조).

세부 정보 보기

그림 02: 세부 정보 보기(전체 크기 이미지를 보려면 클릭)

인덱스 보기는 목록 2에 포함되어 있습니다. 보기 데이터에서 영화 항목이 나타내는 영화 목록을 반복하기만 하면 됩니다.

목록 2 – Views\Home\Index.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>

<%@ Import Namespace="MvcApplication1.Models" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">

<ul>

<% foreach (var m in (IEnumerable<Movie>)ViewData["movies"])
     { %>

     <li><%= m.Title %></li>

<% } %>
</ul>

</asp:Content>

보기 master 페이지는 목록 3에 포함되어 있습니다. 보기 master 페이지는 뷰 데이터에서 범주 항목으로 표시되는 모든 영화 범주를 반복하고 렌더링합니다.

목록 3 – Views\Shared\Site.master

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.Master.cs" Inherits="MvcApplication1.Views.Shared.Site" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
     <title></title>
     <asp:ContentPlaceHolder ID="head" runat="server">

     </asp:ContentPlaceHolder>
</head>
<body>
     <div>
          <h1>My Movie Website</h1>

          <% foreach (var c in (IEnumerable<MovieCategory>)ViewData["categories"])
                           {%>

               <%= Html.ActionLink(c.Name, "Details", new {id=c.Id} ) %> 

          <% } %>


          <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">

          </asp:ContentPlaceHolder>
     </div>
</body>
</html>

모든 데이터는 보기 데이터를 통해 보기 및 보기 master 페이지에 전달됩니다. 이것이 데이터를 master 페이지에 전달하는 올바른 방법입니다.

그렇다면 이 솔루션의 문제점은 무엇일까요? 문제는 이 솔루션이 DRY(자신을 반복하지 않음) 원칙을 위반한다는 것입니다. 각 컨트롤러 작업은 데이터를 보려면 동일한 영화 범주 목록을 추가해야 합니다. 애플리케이션에 중복 코드가 있으면 애플리케이션을 유지 관리, 조정 및 수정하기가 훨씬 더 어려워집니다.

좋은 솔루션

이 섹션에서는 컨트롤러 작업에서 보기 master 페이지로 데이터를 전달하는 대안적이고 더 나은 솔루션을 살펴봅니다. 모든 컨트롤러 작업에서 master 페이지의 동영상 범주를 추가하는 대신 보기 데이터에 영화 범주를 한 번만 추가합니다. 보기 master 페이지에서 사용하는 모든 보기 데이터가 애플리케이션 컨트롤러에 추가됩니다.

ApplicationController 클래스는 목록 4에 포함되어 있습니다.

목록 4 – Controllers\ApplicationController.cs

using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
     public abstract class ApplicationController : Controller
     {
          private MovieDataContext _dataContext = new MovieDataContext();

          public MovieDataContext DataContext
          {
               get { return _dataContext; }
          }

          public ApplicationController()
          {
               ViewData["categories"] = from c in DataContext.MovieCategories 
                         select c;
          }

     }
}

목록 4에서 애플리케이션 컨트롤러에 대해 알아야 할 세 가지 사항이 있습니다. 먼저 클래스는 기본 System.Web.Mvc.Controller 클래스에서 상속됩니다. 애플리케이션 컨트롤러는 컨트롤러 클래스입니다.

둘째, 애플리케이션 컨트롤러 클래스는 추상 클래스입니다. 추상 클래스는 구체적인 클래스에서 구현해야 하는 클래스입니다. 애플리케이션 컨트롤러는 추상 클래스이므로 클래스에 정의된 메서드를 직접 호출할 수 없습니다. Application 클래스를 직접 호출하려고 하면 리소스를 찾을 수 없음 오류 메시지가 표시됩니다.

셋째, 애플리케이션 컨트롤러에는 데이터를 볼 영화 범주 목록을 추가하는 생성자가 포함되어 있습니다. 애플리케이션 컨트롤러에서 상속되는 모든 컨트롤러 클래스는 애플리케이션 컨트롤러의 생성자를 자동으로 호출합니다. 애플리케이션 컨트롤러에서 상속되는 모든 컨트롤러에서 작업을 호출할 때마다 영화 범주가 보기 데이터에 자동으로 포함됩니다.

목록 5의 Movies 컨트롤러는 애플리케이션 컨트롤러에서 상속됩니다.

목록 5 – Controllers\MoviesController.cs

using System.Linq;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
     public class MoviesController : ApplicationController
     {
          /// <summary>

          /// Show list of all movies
          /// </summary>
          public ActionResult Index()
          {
               ViewData["movies"] = from m in DataContext.Movies 
                         select m;
               return View();
          }

          /// <summary>
          /// Show list of movies in a category
          /// </summary>

          public ActionResult Details(int id)
          {
               ViewData["movies"] = from m in DataContext.Movies
                         where m.CategoryId == id
                         select m;
               return View();
          }

     }
}

영화 컨트롤러는 이전 섹션에서 설명한 홈 컨트롤러와 마찬가지로 및 Details()라는 Index() 두 가지 작업 메서드를 노출합니다. 보기 master 페이지에 표시되는 영화 범주 목록은 또는 Details() 메서드의 Index() 데이터를 보기 위해 추가되지 않습니다. Movies 컨트롤러는 애플리케이션 컨트롤러에서 상속되므로 동영상 범주 목록이 자동으로 데이터를 보기 위해 추가됩니다.

보기 master 페이지에 보기 데이터를 추가하는 이 솔루션은 DRY(자신을 반복하지 않음) 원칙을 위반하지 않습니다. 데이터를 보기 위해 동영상 범주 목록을 추가하는 코드는 애플리케이션 컨트롤러의 생성자인 한 위치에만 포함됩니다.

요약

이 자습서에서는 컨트롤러에서 보기 master 페이지로 보기 데이터를 전달하는 두 가지 방법을 설명했습니다. 먼저 간단하지만 접근 방식을 유지하기 어려운 방법을 살펴보았지만 첫 번째 섹션에서는 애플리케이션의 모든 컨트롤러 작업에서 보기 master 페이지에 대한 보기 데이터를 추가하는 방법에 대해 설명했습니다. 우리는 이것이 DRY (자신을 반복하지 마십시오) 원칙을 위반하기 때문에 나쁜 접근 방식이라고 결론을 내렸습니다.

다음으로 보기 master 페이지에서 데이터를 보는 데 필요한 데이터를 추가하기 위한 훨씬 더 나은 전략을 검토했습니다. 각 컨트롤러 작업에서 보기 데이터를 추가하는 대신 애플리케이션 컨트롤러 내에서 보기 데이터를 한 번만 추가했습니다. 이렇게 하면 ASP.NET MVC 애플리케이션의 보기 master 페이지에 데이터를 전달할 때 중복 코드를 방지할 수 있습니다.