이 자습서의 목표는 컨트롤러에서 보기 master 페이지로 데이터를 전달하는 방법을 설명하는 것입니다. 뷰 master 페이지에 데이터를 전달하기 위한 두 가지 전략을 살펴봅니다. 먼저 유지 관리가 어려운 애플리케이션을 만드는 쉬운 솔루션에 대해 설명합니다. 다음으로, 좀 더 초기 작업이 필요하지만 훨씬 더 유지 관리 가능한 애플리케이션을 만드는 훨씬 더 나은 솔루션을 살펴봅니다.
마스터 페이지 보기에 데이터 전달
이 자습서의 목표는 컨트롤러에서 보기 master 페이지로 데이터를 전달하는 방법을 설명하는 것입니다. 뷰 master 페이지에 데이터를 전달하기 위한 두 가지 전략을 살펴봅니다. 먼저 유지 관리가 어려운 애플리케이션을 만드는 쉬운 솔루션에 대해 설명합니다. 다음으로, 좀 더 초기 작업이 필요하지만 훨씬 더 유지 관리 가능한 애플리케이션을 만드는 훨씬 더 나은 솔루션을 살펴봅니다.
문제
동영상 데이터베이스 애플리케이션을 빌드하고 애플리케이션의 모든 페이지에 영화 범주 목록을 표시하려는 경우를 상상해 보세요(그림 1 참조). 또한 영화 범주 목록이 데이터베이스 테이블에 저장되어 있다고 상상해 보세요. 이 경우 데이터베이스에서 범주를 검색하고 보기 master 페이지 내에서 영화 범주 목록을 렌더링하는 것이 좋습니다.
그림 01: 보기 master 페이지에 영화 범주 표시(전체 크기 이미지를 보려면 클릭)
여기에 문제가 있습니다. master 페이지에서 영화 범주 목록을 검색하려면 어떻게 해야 할까요? master 페이지에서 직접 모델 클래스의 메서드를 호출하려고 합니다. 즉, 데이터베이스에서 데이터를 검색하는 코드를 master 페이지에 포함하려고 합니다. 그러나 MVC 컨트롤러를 우회하여 데이터베이스에 액세스하는 것은 MVC 애플리케이션 빌드의 주요 이점 중 하나인 클린 문제 분리를 위반합니다.
MVC 애플리케이션에서는 MVC 뷰와 MVC 모델 간의 모든 상호 작용을 MVC 컨트롤러에서 처리하려고 합니다. 이러한 문제를 분리하면 유지 관리가 가능하고 적응 가능하며 테스트 가능한 애플리케이션이 생성됩니다.
MVC 애플리케이션에서 보기 master 페이지를 포함하여 뷰에 전달된 모든 데이터는 컨트롤러 작업을 통해 뷰에 전달되어야 합니다. 또한 뷰 데이터를 활용하여 데이터를 전달해야 합니다. 이 자습서의 나머지 부분에서는 보기 master 페이지에 뷰 데이터를 전달하는 두 가지 방법을 살펴봅니다.
간단한 솔루션
컨트롤러에서 보기 master 페이지로 보기 데이터를 전달하는 가장 간단한 솔루션부터 살펴보겠습니다. 가장 간단한 솔루션은 각 컨트롤러 작업에서 master 페이지의 보기 데이터를 전달하는 것입니다.
목록 1에서 컨트롤러를 고려합니다. 및 Details()
라는 Index()
두 작업을 노출합니다. Action 메서드는 Index()
Movies 데이터베이스 테이블의 모든 동영상을 반환합니다. 작업 메서드는 Details()
특정 영화 범주의 모든 영화를 반환합니다.
목록 1 – Controllers\HomeController.vb
<HandleError()> _
Public Class HomeController
Inherits System.Web.Mvc.Controller
Private _dataContext As New MovieDataContext()
''' <summary>
''' Show list of all movies
''' </summary>
Function Index()
ViewData("categories") = From c In _dataContext.MovieCategories _
Select c
ViewData("movies") = From m In _dataContext.Movies _
Select m
Return View()
End Function
''' <summary>
''' Show list of movies in a category
''' </summary>
Function Details(ByVal id As Integer)
ViewData("categories") = From c In _dataContext.MovieCategories _
Select c
ViewData("movies") = From m In _dataContext.Movies _
Where m.CategoryId = id _
Select m
Return View()
End Function
End Class
및 Details()
작업 둘 다 Index()
데이터를 보기 위해 두 개의 항목을 추가합니다. 작업은 Index()
범주와 영화라는 두 가지 키를 추가합니다. 범주 키는 보기 master 페이지에 표시되는 영화 범주 목록을 나타냅니다. 영화 키는 인덱스 보기 페이지에 표시되는 영화 목록을 나타냅니다.
또한 이 Details()
작업은 범주와 영화라는 두 개의 키를 추가합니다. 범주 키는 다시 한 번 보기 master 페이지에 표시되는 영화 범주 목록을 나타냅니다. 동영상 키는 세부 정보 보기 페이지에 표시되는 특정 범주의 영화 목록을 나타냅니다(그림 2 참조).
그림 02: 세부 정보 보기(전체 크기 이미지를 보려면 클릭)
인덱스 보기는 목록 2에 포함되어 있습니다. 보기 데이터에서 영화 항목이 나타내는 영화 목록을 반복하기만 하면 됩니다.
목록 2 – Views\Home\Index.aspx
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.vb" Inherits="MvcApplication1.Index" %>
<%@ Import Namespace="MvcApplication1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<ul>
<% For Each m In ViewData("movies")%>
<li><%= m.Title %></li>
<% Next%>
</ul>
</asp:Content>
보기 master 페이지는 목록 3에 포함되어 있습니다. 보기 master 페이지는 보기 데이터에서 범주 항목으로 표시되는 모든 영화 범주를 반복하고 렌더링합니다.
목록 3 – Views\Shared\Site.master
<%@ Master Language="VB" AutoEventWireup="false" CodeBehind="Site.Master.vb" Inherits="MvcApplication1.Site" %>
<%@ Import Namespace="MvcApplication1" %>
<!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>
<% For Each c In ViewData("categories")%>
<%=Html.ActionLink(c.Name, "Details", New With {.id = c.Id})%>
<% Next%>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</body>
</html>
모든 데이터는 보기 데이터를 통해 보기 및 보기 master 페이지로 전달됩니다. master 페이지에 데이터를 전달하는 올바른 방법입니다.
그렇다면 이 솔루션의 문제점은 무엇일까요? 문제는 이 솔루션이 DRY(자신을 반복하지 않음) 원칙을 위반한다는 것입니다. 각 컨트롤러 작업은 데이터를 보려면 동일한 영화 범주 목록을 추가해야 합니다. 애플리케이션에 중복 코드가 있으면 애플리케이션을 유지 관리, 조정 및 수정하기가 훨씬 더 어려워집니다.
좋은 솔루션
이 섹션에서는 컨트롤러 작업에서 보기 master 페이지로 데이터를 전달하는 대체 솔루션과 더 나은 솔루션을 살펴봅니다. 각 컨트롤러 작업에서 master 페이지의 영화 범주를 추가하는 대신 동영상 범주를 보기 데이터에 한 번만 추가합니다. 보기 master 페이지에서 사용하는 모든 보기 데이터는 애플리케이션 컨트롤러에 추가됩니다.
ApplicationController 클래스는 목록 4에 포함되어 있습니다.
ApplicationController 클래스는 목록 4에 포함되어 있습니다.
목록 4 – Controllers\ApplicationController.vb
Public MustInherit Class ApplicationController
Inherits System.Web.Mvc.Controller
Private _dataContext As New MovieDataContext()
Public ReadOnly Property DataContext() As MovieDataContext
Get
Return _dataContext
End Get
End Property
Sub New()
ViewData("categories") = From c In DataContext.MovieCategories _
Select c
End Sub
End Class
목록 4에서 애플리케이션 컨트롤러에 대해 알아야 할 세 가지 사항이 있습니다. 먼저 클래스가 기본 System.Web.Mvc.Controller 클래스에서 상속됩니다. 애플리케이션 컨트롤러는 컨트롤러 클래스입니다.
둘째, 애플리케이션 컨트롤러 클래스는 MustInherit 클래스입니다. MustInherit 클래스는 구체적인 클래스에서 구현해야 하는 클래스입니다. Application 컨트롤러는 MustInherit 클래스이므로 클래스에 정의된 메서드를 직접 호출할 수 없습니다. Application 클래스를 직접 호출하려고 하면 리소스를 찾을 수 없음 오류 메시지가 표시됩니다.
셋째, 애플리케이션 컨트롤러에는 데이터를 볼 영화 범주 목록을 추가하는 생성자가 포함되어 있습니다. 애플리케이션 컨트롤러에서 상속되는 모든 컨트롤러 클래스는 애플리케이션 컨트롤러의 생성자를 자동으로 호출합니다. 애플리케이션 컨트롤러에서 상속되는 모든 컨트롤러에서 작업을 호출할 때마다 영화 범주가 보기 데이터에 자동으로 포함됩니다.
목록 5의 Movies 컨트롤러는 애플리케이션 컨트롤러에서 상속됩니다.
목록 5 – Controllers\MoviesController.vb
<HandleError()> _
Public Class MoviesController
Inherits ApplicationController
''' <summary>
''' Show list of all movies
''' </summary>
Function Index()
ViewData("movies") = From m In DataContext.Movies _
Select m
Return View()
End Function
''' <summary>
''' Show list of movies in a category
''' </summary>
Function Details(ByVal id As Integer)
ViewData("movies") = From m In DataContext.Movies _
Where m.CategoryId = id _
Select m
Return View()
End Function
End Class
이전 섹션에서 설명한 홈 컨트롤러와 마찬가지로 Movies 컨트롤러는 및 Details()
라는 Index()
두 가지 작업 메서드를 노출합니다. 보기 master 페이지에 표시되는 영화 범주 목록은 또는 Details()
메서드의 Index()
데이터를 보기 위해 추가되지 않습니다. Movies 컨트롤러는 애플리케이션 컨트롤러에서 상속되므로 동영상 범주 목록이 자동으로 데이터를 보기 위해 추가됩니다.
보기 master 페이지에 대한 보기 데이터를 추가하는 이 솔루션은 DRY(자신을 반복하지 않음) 원칙을 위반하지 않습니다. 데이터를 보기 위해 영화 범주 목록을 추가하는 코드는 애플리케이션 컨트롤러의 생성자인 한 위치에만 포함됩니다.
요약
이 자습서에서는 컨트롤러에서 보기 master 페이지로 뷰 데이터를 전달하는 두 가지 방법을 설명했습니다. 첫째, 간단하지만 유지 관리하기 어려운 접근 방식을 검토했습니다. 첫 번째 섹션에서는 애플리케이션의 각 컨트롤러 작업에서 보기 master 페이지에 대한 보기 데이터를 추가하는 방법을 설명했습니다. 우리는 이것이 DRY (자신을 반복하지 마십시오) 원칙을 위반하기 때문에 나쁜 접근 방식이라고 결론을 내렸습니다.
다음으로 보기 master 페이지에서 데이터를 보는 데 필요한 데이터를 추가하기 위한 훨씬 더 나은 전략을 검토했습니다. 각 컨트롤러 작업에서 보기 데이터를 추가하는 대신 애플리케이션 컨트롤러 내에서 보기 데이터를 한 번만 추가했습니다. 이렇게 하면 ASP.NET MVC 애플리케이션의 보기 master 페이지에 데이터를 전달할 때 중복 코드를 방지할 수 있습니다.