3부. ASP.NET Core MVC 앱에 뷰 추가

참고 항목

이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Important

이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.

현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

작성자: Rick Anderson

이 섹션에서는 Razor 뷰 파일을 사용하도록 HelloWorldController 클래스를 수정합니다. 그러면 클라이언트에 대한 HTML 응답을 생성하는 프로세스가 깔끔하게 캡슐화됩니다.

Razor를 사용하여 뷰 템플릿을 만듭니다. Razor 기반 뷰 템플릿은 다음과 같습니다.

  • 파일 확장명은 .cshtml입니다.
  • C#으로 HTML 출력을 만드는 세련된 방법을 제공합니다.

현재 Index 메서드는 컨트롤러 클래스에서 메시지와 함께 문자열을 반환합니다. HelloWorldController 클래스에서 Index 메서드를 다음 코드로 바꿉니다.

public IActionResult Index()
{
    return View();
}

앞의 코드가 하는 역할은 다음과 같습니다.

  • 컨트롤러의 View 메서드를 호출합니다.
  • 뷰 템플릿을 사용하여 HTML 응답을 생성합니다.

컨트롤러 메서드:

  • ‘작업 메서드’라고 합니다. 예를 들어 위의 코드에는 Index 작업 메서드가 있습니다.
  • 일반적으로 string 같은 형식이 아니라 ActionResult에서 파생된 클래스 또는 IActionResult를 반환합니다.

보기 추가

Views 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 > 새 폴더를 클릭하고 폴더의 이름을 HelloWorld로 지정합니다.

Views/HelloWorld 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 > 새 항목을 클릭합니다.

새 항목 추가 대화 상자에서 모든 템플릿 표시를 선택합니다.

새 항목 추가 - MvcMovie 대화 상자에서 다음을 수행합니다.

  • 오른쪽 위의 검색 상자에 를 입력합니다.
  • Razor 뷰 - 비어 있음을 선택합니다.
  • 이름 상자 값을 Index.cshtml유지합니다.
  • 추가 선택

새 항목 추가 대화 상자

Views/HelloWorld/Index.cshtmlRazor 뷰 파일의 콘텐츠를 다음으로 바꿉니다.

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

https://localhost:{PORT}/HelloWorld로 이동합니다.

  • HelloWorldControllerIndex 메서드는 return View(); 문을 실행했습니다. 이 문은 메서드가 뷰 템플릿 파일을 사용하여 브라우저에 대한 응답을 렌더링해야 함을 지정합니다.

  • 뷰 템플릿 파일 이름을 지정하지 않았으므로 MVC는 기본 뷰 파일을 사용하도록 기본 설정되었습니다. 뷰 파일 이름을 지정하지 않으면 기본 뷰가 반환됩니다. 이 예제에서 기본 뷰는 작업 메서드 Index와 동일한 이름을 갖습니다. 보기 템플릿 /Views/HelloWorld/Index.cshtml 이 사용됩니다.

  • 다음 이미지는 뷰에서 하드 코드된 "Hello from our View Template!" 문자열을 보여 줍니다.

    브라우저 창

보기 및 레이아웃 페이지 변경

메뉴 링크 MvcMovie, Home, Privacy를 선택합니다. 각 페이지는 동일한 메뉴 레이아웃을 표시합니다. 메뉴 레이아웃은 파일에서 Views/Shared/_Layout.cshtml 구현됩니다.

Views/Shared/_Layout.cshtml 파일을 엽니다.

레이아웃 템플릿에서는 다음 작업을 할 수 있습니다.

  • 사이트의 HTML 컨테이너 레이아웃을 한 곳에 지정
  • 사이트의 여러 페이지에 HTML 컨테이너 레이아웃 적용

@RenderBody() 줄을 찾습니다. RenderBody는 사용자가 만드는 모든 보기 전용 페이지가 표시되는 자리 표시자이며 레이아웃 페이지에서 래핑됩니다. 예를 들어 Privacy 링크를 선택하는 경우 Views/Home/Privacy.cshtml 뷰는 RenderBody 메서드 내에서 렌더링됩니다.

Views/Shared/_Layout.cshtml 파일의 내용을 다음 태그로 대체합니다. 변경 내용이 강조 표시되어 있습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Movie App</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container-fluid">
                <a class="navbar-brand" asp-area="" asp-controller="Movies" asp-action="Index">Movie App</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2023 - Movie App - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

위에 태그에서는 다음과 같은 변경을 수행했습니다.

  • 세 번 나오는 MvcMovieMovie App으로 변경했습니다.
  • 앵커 요소 <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">MvcMovie</a><a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>로 변경했습니다.

이 앱은 영역을 사용하지 않기 때문에 위의 태그에서 asp-area=""앵커 태그 도우미 특성 및 특성 값이 생략되었습니다.

참고: Movies 컨트롤러는 구현되지 않았습니다. 지금은 Movie App 링크가 작동하지 않습니다.

변경 내용을 저장하고 Privacy 링크를 선택합니다. 브라우저 탭의 제목에 Privacy Policy - MvcMovie 대신 Privacy Policy - Movie App이 표시됨을 확인합니다.

Privacy 탭

Home 링크를 선택합니다.

제목 및 앵커 텍스트에 Movie App이 표시됩니다. 레이아웃 템플릿은 한 번 변경되었으며 사이트의 모든 페이지에 새 링크 텍스트 및 새 제목이 반영됩니다.

Views/_ViewStart.cshtml 파일을 검사합니다.

@{
    Layout = "_Layout";
}

파일은 Views/_ViewStart.cshtml 각 보기에 Views/Shared/_Layout.cshtml 파일을 가져옵니다. Layout 속성을 사용하여 다른 레이아웃 보기를 설정하거나 레이아웃 파일을 사용하지 않도록 null로 설정할 수 있습니다.

Views/HelloWorld/Index.cshtml 뷰 파일을 엽니다.

다음에 강조 표시된 대로 제목과 <h2> 요소를 변경합니다.

@{
    ViewData["Title"] = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

제목과 <h2> 요소가 약간 다르기 때문에 코드의 어떤 부분에서 표시가 변경되는지가 명확합니다.

위의 코드에서 ViewData["Title"] = "Movie List";ViewData 사전의 Title 속성을 "Movie List"로 설정합니다. Title 속성은 레이아웃 페이지의 <title> HTML 요소에서 사용됩니다.

<title>@ViewData["Title"] - Movie App</title>

변경 내용을 저장하고 https://localhost:{PORT}/HelloWorld로 이동합니다.

다음 사항이 변경되었습니다.

  • 브라우저 제목
  • 기본 제목
  • 보조 제목

브라우저에 변경 내용이 없으면 보고 있는 캐시된 콘텐츠일 수 있습니다. 브라우저에서 Ctrl+F5를 눌러 서버의 응답이 강제로 로드되도록 합니다. 브라우저 제목은 Index.cshtml 뷰 템플릿에서 설정한 ViewData["Title"] 및 레이아웃 파일에 추가된 추가 “- Movie App”으로 만들어집니다.

보기 템플릿의 Index.cshtml 콘텐츠는 보기 템플릿과 Views/Shared/_Layout.cshtml 병합됩니다. 단일 HTML 응답이 브라우저로 전송되었습니다. 레이아웃 템플릿을 사용하면 응용 프로그램의 모든 페이지에 걸쳐 적용되는 변경 내용을 쉽게 만들 수 있습니다. 자세한 내용은 레이아웃을 참조하세요.

영화 목록 보기

그러나 작은 양의 "데이터"인 "Hello from our View Template!" 메시지는 하드 코드되어 있습니다. MVC 애플리케이션에는 “V”(뷰)와 “C”(컨트롤러)가 있지만 “M”(모델)은 아직 없습니다.

컨트롤러에서 보기로 데이터 전달

컨트롤러 작업은 들어오는 URL 요청에 대한 응답으로 호출됩니다. 컨트롤러 클래스는 들어오는 브라우저 요청을 처리하는 코드가 작성된 위치입니다. 컨트롤러는 데이터 원본에서 데이터를 검색하고 브라우저에 다시 전송할 응답의 유형을 결정합니다. 보기 템플릿은 브라우저에 대한 HTML 응답을 만들고 서식을 지정하기 위해서 컨트롤러에서 사용될 수 있습니다.

컨트롤러는 보기 템플릿에서 응답을 렌더링하기 위해 필요한 데이터를 제공할 책임이 있습니다.

뷰 템플릿은 다음을 수행하면 안 됩니다.

  • 비즈니스 논리 수행
  • 데이터베이스와 직접 상호 작용

뷰 템플릿은 컨트롤러에서 제공하는 데이터만 사용해야 합니다. 이 “문제의 분리”를 유지 관리하면 코드를 다음과 같이 유지할 수 있습니다.

  • 정리
  • 테스트 가능
  • 유지 관리 가능

현재 HelloWorldController 클래스에서 Welcome 메서드는 nameID 매개 변수를 가져온 다음, 값을 브라우저로 직접 출력합니다.

컨트롤러가 이 응답을 문자열로 렌더링하게 하는 대신, 보기 템플릿을 사용하도록 컨트롤러를 변경합니다. 보기 템플릿은 동적 응답을 생성합니다. 즉, 응답을 생성하려면 컨트롤러에서 뷰로 적절한 데이터를 전달해야 한다는 의미입니다. 컨트롤러가 뷰 템플릿에 필요한 동적 데이터(매개 변수)를 ViewData 사전에 넣도록 하면 됩니다. 그러면 뷰 템플릿이 동적 데이터에 액세스할 수 있습니다.

에서 HelloWorldController.cs메서드를 Welcome 변경하여 사전에 a MessageNumTimes 값을 ViewData 추가합니다.

ViewData 사전은 동적 개체로, 모든 형식을 사용할 수 있다는 의미입니다. ViewData 개체는 항목이 추가될 때까지 정의된 속성이 없습니다. MVC 모델 바인딩 시스템은 쿼리 문자열에서 메서드의 매개 변수로 명명된 매개 변수(namenumTimes)를 자동으로 매핑합니다. 완료된 HelloWorldController는 다음과 같습니다.

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers;

public class HelloWorldController : Controller
{
    public IActionResult Index()
    {
        return View();
    }
    public IActionResult Welcome(string name, int numTimes = 1)
    {
        ViewData["Message"] = "Hello " + name;
        ViewData["NumTimes"] = numTimes;
        return View();
    }
}

ViewData 사전 개체는 보기에 전달될 데이터를 담고 있습니다.

라는 시작 보기 템플릿을 만듭니다 Views/HelloWorld/Welcome.cshtml.

Welcome.cshtml 뷰 템플릿에 “Hello” NumTimes를 표시하는 반복을 만듭니다. Views/HelloWorld/Welcome.cshtml의 내용을 다음으로 바꿉니다.

@{
    ViewData["Title"] = "Welcome";
}

<h2>Welcome</h2>

<ul>
    @for (int i = 0; i < (int)ViewData["NumTimes"]!; i++)
    {
        <li>@ViewData["Message"]</li>
    }
</ul>

변경 내용을 저장하고 다음 URL로 이동합니다.

https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

데이터는 URL에서 가져와서 MVC 모델 바인더를 사용하여 컨트롤러에 전달됩니다. 컨트롤러는 데이터를 ViewData 사전으로 패키징하고 해당 개체를 보기에 전달합니다. 그런 다음 보기는 데이터를 HTML로 브라우저에 렌더링합니다.

Privacy 시작 레이블과 Hello Rick이 네 번 표시된 문구를 보여 주는 보기

위 샘플에서는 컨트롤러에서 뷰로 데이터를 전달하는 데 ViewData 사전이 사용되었습니다. 자습서의 뒷부분에서는 컨트롤러에서 보기로 데이터를 전달하기 위해 보기 모델이 사용됩니다. 데이터를 전달하는 뷰 모델 접근 방식이 ViewData 사전 접근 방식보다 선호됩니다.

다음 자습서에서는 영화 데이터베이스가 만들어집니다.

이 섹션에서는 Razor 뷰 파일을 사용하도록 HelloWorldController 클래스를 수정합니다. 그러면 클라이언트에 대한 HTML 응답을 생성하는 프로세스가 깔끔하게 캡슐화됩니다.

Razor를 사용하여 뷰 템플릿을 만듭니다. Razor 기반 뷰 템플릿은 다음과 같습니다.

  • 파일 확장명은 .cshtml입니다.
  • C#으로 HTML 출력을 만드는 세련된 방법을 제공합니다.

현재 Index 메서드는 컨트롤러 클래스에서 메시지와 함께 문자열을 반환합니다. HelloWorldController 클래스에서 Index 메서드를 다음 코드로 바꿉니다.

public IActionResult Index()
{
    return View();
}

앞의 코드가 하는 역할은 다음과 같습니다.

  • 컨트롤러의 View 메서드를 호출합니다.
  • 뷰 템플릿을 사용하여 HTML 응답을 생성합니다.

컨트롤러 메서드:

  • ‘작업 메서드’라고 합니다. 예를 들어 위의 코드에는 Index 작업 메서드가 있습니다.
  • 일반적으로 string 같은 형식이 아니라 ActionResult에서 파생된 클래스 또는 IActionResult를 반환합니다.

보기 추가

Views 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 > 새 폴더를 클릭하고 폴더의 이름을 HelloWorld로 지정합니다.

Views/HelloWorld 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 > 새 항목을 클릭합니다.

새 항목 추가 - MvcMovie 대화 상자에서 다음을 수행합니다.

  • 오른쪽 위의 검색 상자에 를 입력합니다.
  • Razor 뷰 - 비어 있음을 선택합니다.
  • 이름 상자 값을 Index.cshtml유지합니다.
  • 추가 선택

새 항목 추가 대화 상자

Views/HelloWorld/Index.cshtmlRazor 뷰 파일의 콘텐츠를 다음으로 바꿉니다.

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

https://localhost:{PORT}/HelloWorld로 이동합니다.

  • HelloWorldControllerIndex 메서드는 return View(); 문을 실행했습니다. 이 문은 메서드가 뷰 템플릿 파일을 사용하여 브라우저에 대한 응답을 렌더링해야 함을 지정합니다.

  • 뷰 템플릿 파일 이름을 지정하지 않았으므로 MVC는 기본 뷰 파일을 사용하도록 기본 설정되었습니다. 뷰 파일 이름을 지정하지 않으면 기본 뷰가 반환됩니다. 이 예제에서 기본 뷰는 작업 메서드 Index와 동일한 이름을 갖습니다. 보기 템플릿 /Views/HelloWorld/Index.cshtml 이 사용됩니다.

  • 다음 이미지는 뷰에서 하드 코드된 "Hello from our View Template!" 문자열을 보여 줍니다.

    브라우저 창

보기 및 레이아웃 페이지 변경

메뉴 링크 MvcMovie, Home, Privacy를 선택합니다. 각 페이지는 동일한 메뉴 레이아웃을 표시합니다. 메뉴 레이아웃은 파일에서 Views/Shared/_Layout.cshtml 구현됩니다.

Views/Shared/_Layout.cshtml 파일을 엽니다.

레이아웃 템플릿에서는 다음 작업을 할 수 있습니다.

  • 사이트의 HTML 컨테이너 레이아웃을 한 곳에 지정
  • 사이트의 여러 페이지에 HTML 컨테이너 레이아웃 적용

@RenderBody() 줄을 찾습니다. RenderBody는 사용자가 만드는 모든 보기 전용 페이지가 표시되는 자리 표시자이며 레이아웃 페이지에서 래핑됩니다. 예를 들어 Privacy 링크를 선택하는 경우 Views/Home/Privacy.cshtml 뷰는 RenderBody 메서드 내에서 렌더링됩니다.

Views/Shared/_Layout.cshtml 파일의 내용을 다음 태그로 대체합니다. 변경 내용이 강조 표시되어 있습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Movie App</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container-fluid">
                <a class="navbar-brand" asp-area="" asp-controller="Movies" asp-action="Index">Movie App</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2022 - Movie App - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

위에 태그에서는 다음과 같은 변경을 수행했습니다.

  • 세 번 나오는 MvcMovieMovie App으로 변경했습니다.
  • 앵커 요소 <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">MvcMovie</a><a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>로 변경했습니다.

이 앱은 영역을 사용하지 않기 때문에 위의 태그에서 asp-area=""앵커 태그 도우미 특성 및 특성 값이 생략되었습니다.

참고: Movies 컨트롤러는 구현되지 않았습니다. 지금은 Movie App 링크가 작동하지 않습니다.

변경 내용을 저장하고 Privacy 링크를 선택합니다. 브라우저 탭의 제목에 Privacy Policy - MvcMovie 대신 Privacy Policy - Movie App이 표시됨을 확인합니다.

Privacy 탭

Home 링크를 선택합니다.

제목 및 앵커 텍스트에 Movie App이 표시됩니다. 레이아웃 템플릿은 한 번 변경되었으며 사이트의 모든 페이지에 새 링크 텍스트 및 새 제목이 반영됩니다.

Views/_ViewStart.cshtml 파일을 검사합니다.

@{
    Layout = "_Layout";
}

파일은 Views/_ViewStart.cshtml 각 보기에 Views/Shared/_Layout.cshtml 파일을 가져옵니다. Layout 속성을 사용하여 다른 레이아웃 보기를 설정하거나 레이아웃 파일을 사용하지 않도록 null로 설정할 수 있습니다.

Views/HelloWorld/Index.cshtml 뷰 파일을 엽니다.

다음에 강조 표시된 대로 제목과 <h2> 요소를 변경합니다.

@{
    ViewData["Title"] = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

제목과 <h2> 요소가 약간 다르기 때문에 코드의 어떤 부분에서 표시가 변경되는지가 명확합니다.

위의 코드에서 ViewData["Title"] = "Movie List";ViewData 사전의 Title 속성을 "Movie List"로 설정합니다. Title 속성은 레이아웃 페이지의 <title> HTML 요소에서 사용됩니다.

<title>@ViewData["Title"] - Movie App</title>

변경 내용을 저장하고 https://localhost:{PORT}/HelloWorld로 이동합니다.

다음 사항이 변경되었습니다.

  • 브라우저 제목
  • 기본 제목
  • 보조 제목

브라우저에 변경 내용이 없으면 보고 있는 캐시된 콘텐츠일 수 있습니다. 브라우저에서 Ctrl+F5를 눌러 서버의 응답이 강제로 로드되도록 합니다. 브라우저 제목은 Index.cshtml 뷰 템플릿에서 설정한 ViewData["Title"] 및 레이아웃 파일에 추가된 추가 “- Movie App”으로 만들어집니다.

보기 템플릿의 Index.cshtml 콘텐츠는 보기 템플릿과 Views/Shared/_Layout.cshtml 병합됩니다. 단일 HTML 응답이 브라우저로 전송되었습니다. 레이아웃 템플릿을 사용하면 응용 프로그램의 모든 페이지에 걸쳐 적용되는 변경 내용을 쉽게 만들 수 있습니다. 자세한 내용은 레이아웃을 참조하세요.

영화 목록 보기

그러나 작은 양의 "데이터"인 "Hello from our View Template!" 메시지는 하드 코드되어 있습니다. MVC 애플리케이션에는 “V”(뷰)와 “C”(컨트롤러)가 있지만 “M”(모델)은 아직 없습니다.

컨트롤러에서 보기로 데이터 전달

컨트롤러 작업은 들어오는 URL 요청에 대한 응답으로 호출됩니다. 컨트롤러 클래스는 들어오는 브라우저 요청을 처리하는 코드가 작성된 위치입니다. 컨트롤러는 데이터 원본에서 데이터를 검색하고 브라우저에 다시 전송할 응답의 유형을 결정합니다. 보기 템플릿은 브라우저에 대한 HTML 응답을 만들고 서식을 지정하기 위해서 컨트롤러에서 사용될 수 있습니다.

컨트롤러는 보기 템플릿에서 응답을 렌더링하기 위해 필요한 데이터를 제공할 책임이 있습니다.

뷰 템플릿은 다음을 수행하면 안 됩니다.

  • 비즈니스 논리 수행
  • 데이터베이스와 직접 상호 작용

뷰 템플릿은 컨트롤러에서 제공하는 데이터만 사용해야 합니다. 이 “문제의 분리”를 유지 관리하면 코드를 다음과 같이 유지할 수 있습니다.

  • 정리
  • 테스트 가능
  • 유지 관리 가능

현재 HelloWorldController 클래스에서 Welcome 메서드는 nameID 매개 변수를 가져온 다음, 값을 브라우저로 직접 출력합니다.

컨트롤러가 이 응답을 문자열로 렌더링하게 하는 대신, 보기 템플릿을 사용하도록 컨트롤러를 변경합니다. 보기 템플릿은 동적 응답을 생성합니다. 즉, 응답을 생성하려면 컨트롤러에서 뷰로 적절한 데이터를 전달해야 한다는 의미입니다. 컨트롤러가 뷰 템플릿에 필요한 동적 데이터(매개 변수)를 ViewData 사전에 넣도록 하면 됩니다. 그러면 뷰 템플릿이 동적 데이터에 액세스할 수 있습니다.

에서 HelloWorldController.cs메서드를 Welcome 변경하여 사전에 a MessageNumTimes 값을 ViewData 추가합니다.

ViewData 사전은 동적 개체로, 모든 형식을 사용할 수 있다는 의미입니다. ViewData 개체는 항목이 추가될 때까지 정의된 속성이 없습니다. MVC 모델 바인딩 시스템은 쿼리 문자열에서 메서드의 매개 변수로 명명된 매개 변수(namenumTimes)를 자동으로 매핑합니다. 완료된 HelloWorldController는 다음과 같습니다.

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers;

public class HelloWorldController : Controller
{
    public IActionResult Index()
    {
        return View();
    }
    public IActionResult Welcome(string name, int numTimes = 1)
    {
        ViewData["Message"] = "Hello " + name;
        ViewData["NumTimes"] = numTimes;
        return View();
    }
}

ViewData 사전 개체는 보기에 전달될 데이터를 담고 있습니다.

라는 시작 보기 템플릿을 만듭니다 Views/HelloWorld/Welcome.cshtml.

Welcome.cshtml 뷰 템플릿에 “Hello” NumTimes를 표시하는 반복을 만듭니다. Views/HelloWorld/Welcome.cshtml의 내용을 다음으로 바꿉니다.

@{
    ViewData["Title"] = "Welcome";
}

<h2>Welcome</h2>

<ul>
    @for (int i = 0; i < (int)ViewData["NumTimes"]!; i++)
    {
        <li>@ViewData["Message"]</li>
    }
</ul>

변경 내용을 저장하고 다음 URL로 이동합니다.

https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

데이터는 URL에서 가져와서 MVC 모델 바인더를 사용하여 컨트롤러에 전달됩니다. 컨트롤러는 데이터를 ViewData 사전으로 패키징하고 해당 개체를 보기에 전달합니다. 그런 다음 보기는 데이터를 HTML로 브라우저에 렌더링합니다.

Privacy 시작 레이블과 Hello Rick이 네 번 표시된 문구를 보여 주는 보기

위 샘플에서는 컨트롤러에서 뷰로 데이터를 전달하는 데 ViewData 사전이 사용되었습니다. 자습서의 뒷부분에서는 컨트롤러에서 보기로 데이터를 전달하기 위해 보기 모델이 사용됩니다. 데이터를 전달하는 뷰 모델 접근 방식이 ViewData 사전 접근 방식보다 선호됩니다.

다음 자습서에서는 영화 데이터베이스가 만들어집니다.

이 섹션에서는 Razor 뷰 파일을 사용하도록 HelloWorldController 클래스를 수정합니다. 그러면 클라이언트에 대한 HTML 응답을 생성하는 프로세스가 깔끔하게 캡슐화됩니다.

Razor를 사용하여 뷰 템플릿을 만듭니다. Razor 기반 뷰 템플릿은 다음과 같습니다.

  • 파일 확장명은 .cshtml입니다.
  • C#으로 HTML 출력을 만드는 세련된 방법을 제공합니다.

현재 Index 메서드는 컨트롤러 클래스에서 메시지와 함께 문자열을 반환합니다. HelloWorldController 클래스에서 Index 메서드를 다음 코드로 바꿉니다.

public IActionResult Index()
{
    return View();
}

앞의 코드가 하는 역할은 다음과 같습니다.

  • 컨트롤러의 View 메서드를 호출합니다.
  • 뷰 템플릿을 사용하여 HTML 응답을 생성합니다.

컨트롤러 메서드:

  • ‘작업 메서드’라고 합니다. 예를 들어 위의 코드에는 Index 작업 메서드가 있습니다.
  • 일반적으로 string 같은 형식이 아니라 ActionResult에서 파생된 클래스 또는 IActionResult를 반환합니다.

보기 추가

Views 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 > 새 폴더를 클릭하고 폴더의 이름을 HelloWorld로 지정합니다.

Views/HelloWorld 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 > 새 항목을 클릭합니다.

새 항목 추가 - MvcMovie 대화 상자에서 다음을 수행합니다.

  • 오른쪽 위의 검색 상자에 를 입력합니다.
  • Razor 뷰 - 비어 있음을 선택합니다.
  • 이름 상자 값을 Index.cshtml유지합니다.
  • 추가 선택

새 항목 추가 대화 상자

Views/HelloWorld/Index.cshtmlRazor 뷰 파일의 콘텐츠를 다음으로 바꿉니다.

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

https://localhost:{PORT}/HelloWorld로 이동합니다.

  • HelloWorldControllerIndex 메서드는 return View(); 문을 실행했습니다. 이 문은 메서드가 뷰 템플릿 파일을 사용하여 브라우저에 대한 응답을 렌더링해야 함을 지정합니다.

  • 뷰 템플릿 파일 이름을 지정하지 않았으므로 MVC는 기본 뷰 파일을 사용하도록 기본 설정되었습니다. 뷰 파일 이름을 지정하지 않으면 기본 뷰가 반환됩니다. 이 예제에서 기본 뷰는 작업 메서드 Index와 동일한 이름을 갖습니다. 보기 템플릿 /Views/HelloWorld/Index.cshtml 이 사용됩니다.

  • 다음 이미지는 뷰에서 하드 코드된 "Hello from our View Template!" 문자열을 보여 줍니다.

    브라우저 창

보기 및 레이아웃 페이지 변경

메뉴 링크 MvcMovie, Home, Privacy를 선택합니다. 각 페이지는 동일한 메뉴 레이아웃을 표시합니다. 메뉴 레이아웃은 파일에서 Views/Shared/_Layout.cshtml 구현됩니다.

Views/Shared/_Layout.cshtml 파일을 엽니다.

레이아웃 템플릿에서는 다음 작업을 할 수 있습니다.

  • 사이트의 HTML 컨테이너 레이아웃을 한 곳에 지정
  • 사이트의 여러 페이지에 HTML 컨테이너 레이아웃 적용

@RenderBody() 줄을 찾습니다. RenderBody는 사용자가 만드는 모든 보기 전용 페이지가 표시되는 자리 표시자이며 레이아웃 페이지에서 래핑됩니다. 예를 들어 Privacy 링크를 선택하는 경우 Views/Home/Privacy.cshtml 뷰는 RenderBody 메서드 내에서 렌더링됩니다.

Views/Shared/_Layout.cshtml 파일의 내용을 다음 태그로 대체합니다. 변경 내용이 강조 표시되어 있습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Movie App</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container-fluid">
                <a class="navbar-brand" asp-area="" asp-controller="Movies" asp-action="Index">Movie App</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - Movie App - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

위에 태그에서는 다음과 같은 변경을 수행했습니다.

  • 세 번 나오는 MvcMovieMovie App으로 변경했습니다.
  • 앵커 요소 <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">MvcMovie</a><a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>로 변경했습니다.

이 앱은 영역을 사용하지 않기 때문에 위의 태그에서 asp-area=""앵커 태그 도우미 특성 및 특성 값이 생략되었습니다.

참고: Movies 컨트롤러는 구현되지 않았습니다. 지금은 Movie App 링크가 작동하지 않습니다.

변경 내용을 저장하고 Privacy 링크를 선택합니다. 브라우저 탭의 제목에 Privacy Policy - MvcMovie 대신 Privacy Policy - Movie App이 표시됨을 확인합니다.

Privacy 탭

Home 링크를 선택합니다.

제목 및 앵커 텍스트에 Movie App이 표시됩니다. 레이아웃 템플릿은 한 번 변경되었으며 사이트의 모든 페이지에 새 링크 텍스트 및 새 제목이 반영됩니다.

Views/_ViewStart.cshtml 파일을 검사합니다.

@{
    Layout = "_Layout";
}

파일은 Views/_ViewStart.cshtml 각 보기에 Views/Shared/_Layout.cshtml 파일을 가져옵니다. Layout 속성을 사용하여 다른 레이아웃 보기를 설정하거나 레이아웃 파일을 사용하지 않도록 null로 설정할 수 있습니다.

Views/HelloWorld/Index.cshtml 뷰 파일을 엽니다.

다음에 강조 표시된 대로 제목과 <h2> 요소를 변경합니다.

@{
    ViewData["Title"] = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

제목과 <h2> 요소가 약간 다르기 때문에 코드의 어떤 부분에서 표시가 변경되는지가 명확합니다.

위의 코드에서 ViewData["Title"] = "Movie List";ViewData 사전의 Title 속성을 "Movie List"로 설정합니다. Title 속성은 레이아웃 페이지의 <title> HTML 요소에서 사용됩니다.

<title>@ViewData["Title"] - Movie App</title>

변경 내용을 저장하고 https://localhost:{PORT}/HelloWorld로 이동합니다.

다음 사항이 변경되었습니다.

  • 브라우저 제목
  • 기본 제목
  • 보조 제목

브라우저에 변경 내용이 없으면 보고 있는 캐시된 콘텐츠일 수 있습니다. 브라우저에서 Ctrl+F5를 눌러 서버의 응답이 강제로 로드되도록 합니다. 브라우저 제목은 Index.cshtml 뷰 템플릿에서 설정한 ViewData["Title"] 및 레이아웃 파일에 추가된 추가 “- Movie App”으로 만들어집니다.

보기 템플릿의 Index.cshtml 콘텐츠는 보기 템플릿과 Views/Shared/_Layout.cshtml 병합됩니다. 단일 HTML 응답이 브라우저로 전송되었습니다. 레이아웃 템플릿을 사용하면 응용 프로그램의 모든 페이지에 걸쳐 적용되는 변경 내용을 쉽게 만들 수 있습니다. 자세한 내용은 레이아웃을 참조하세요.

영화 목록 보기

그러나 작은 양의 "데이터"인 "Hello from our View Template!" 메시지는 하드 코드되어 있습니다. MVC 애플리케이션에는 “V”(뷰)와 “C”(컨트롤러)가 있지만 “M”(모델)은 아직 없습니다.

컨트롤러에서 보기로 데이터 전달

컨트롤러 작업은 들어오는 URL 요청에 대한 응답으로 호출됩니다. 컨트롤러 클래스는 들어오는 브라우저 요청을 처리하는 코드가 작성된 위치입니다. 컨트롤러는 데이터 원본에서 데이터를 검색하고 브라우저에 다시 전송할 응답의 유형을 결정합니다. 보기 템플릿은 브라우저에 대한 HTML 응답을 만들고 서식을 지정하기 위해서 컨트롤러에서 사용될 수 있습니다.

컨트롤러는 보기 템플릿에서 응답을 렌더링하기 위해 필요한 데이터를 제공할 책임이 있습니다.

뷰 템플릿은 다음을 수행하면 안 됩니다.

  • 비즈니스 논리 수행
  • 데이터베이스와 직접 상호 작용

뷰 템플릿은 컨트롤러에서 제공하는 데이터만 사용해야 합니다. 이 “문제의 분리”를 유지 관리하면 코드를 다음과 같이 유지할 수 있습니다.

  • 정리
  • 테스트 가능
  • 유지 관리 가능

현재 HelloWorldController 클래스에서 Welcome 메서드는 nameID 매개 변수를 가져온 다음, 값을 브라우저로 직접 출력합니다.

컨트롤러가 이 응답을 문자열로 렌더링하게 하는 대신, 보기 템플릿을 사용하도록 컨트롤러를 변경합니다. 보기 템플릿은 동적 응답을 생성합니다. 즉, 응답을 생성하려면 컨트롤러에서 뷰로 적절한 데이터를 전달해야 한다는 의미입니다. 컨트롤러가 뷰 템플릿에 필요한 동적 데이터(매개 변수)를 ViewData 사전에 넣도록 하면 됩니다. 그러면 뷰 템플릿이 동적 데이터에 액세스할 수 있습니다.

에서 HelloWorldController.cs메서드를 Welcome 변경하여 사전에 a MessageNumTimes 값을 ViewData 추가합니다.

ViewData 사전은 동적 개체로, 모든 형식을 사용할 수 있다는 의미입니다. ViewData 개체는 항목이 추가될 때까지 정의된 속성이 없습니다. MVC 모델 바인딩 시스템은 쿼리 문자열에서 메서드의 매개 변수로 명명된 매개 변수(namenumTimes)를 자동으로 매핑합니다. 완료된 HelloWorldController는 다음과 같습니다.

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
    public class HelloWorldController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Welcome(string name, int numTimes = 1)
        {
            ViewData["Message"] = "Hello " + name;
            ViewData["NumTimes"] = numTimes;

            return View();
        }
    }
}

ViewData 사전 개체는 보기에 전달될 데이터를 담고 있습니다.

라는 시작 보기 템플릿을 만듭니다 Views/HelloWorld/Welcome.cshtml.

Welcome.cshtml 뷰 템플릿에 “Hello” NumTimes를 표시하는 반복을 만듭니다. Views/HelloWorld/Welcome.cshtml의 내용을 다음으로 바꿉니다.

@{
    ViewData["Title"] = "Welcome";
}

<h2>Welcome</h2>

<ul>
    @for (int i = 0; i < (int)ViewData["NumTimes"]!; i++)
    {
        <li>@ViewData["Message"]</li>
    }
</ul>

변경 내용을 저장하고 다음 URL로 이동합니다.

https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

데이터는 URL에서 가져와서 MVC 모델 바인더를 사용하여 컨트롤러에 전달됩니다. 컨트롤러는 데이터를 ViewData 사전으로 패키징하고 해당 개체를 보기에 전달합니다. 그런 다음 보기는 데이터를 HTML로 브라우저에 렌더링합니다.

Privacy 시작 레이블과 Hello Rick이 네 번 표시된 문구를 보여 주는 보기

위 샘플에서는 컨트롤러에서 뷰로 데이터를 전달하는 데 ViewData 사전이 사용되었습니다. 자습서의 뒷부분에서는 컨트롤러에서 보기로 데이터를 전달하기 위해 보기 모델이 사용됩니다. 데이터를 전달하는 뷰 모델 접근 방식이 ViewData 사전 접근 방식보다 선호됩니다.

다음 자습서에서는 영화 데이터베이스가 만들어집니다.

이 섹션에서는 Razor 뷰 파일을 사용하도록 HelloWorldController 클래스를 수정합니다. 그러면 클라이언트에 대한 HTML 응답을 생성하는 프로세스가 깔끔하게 캡슐화됩니다.

Razor를 사용하여 뷰 템플릿을 만듭니다. Razor 기반 뷰 템플릿은 다음과 같습니다.

  • 파일 확장명은 .cshtml입니다.
  • C#으로 HTML 출력을 만드는 세련된 방법을 제공합니다.

현재 Index 메서드는 컨트롤러 클래스에서 메시지와 함께 문자열을 반환합니다. HelloWorldController 클래스에서 Index 메서드를 다음 코드로 바꿉니다.

public IActionResult Index()
{
    return View();
}

앞의 코드가 하는 역할은 다음과 같습니다.

  • 컨트롤러의 View 메서드를 호출합니다.
  • 뷰 템플릿을 사용하여 HTML 응답을 생성합니다.

컨트롤러 메서드:

  • ‘작업 메서드’라고 합니다. 예를 들어 위의 코드에는 Index 작업 메서드가 있습니다.
  • 일반적으로 string 같은 형식이 아니라 ActionResult에서 파생된 클래스 또는 IActionResult를 반환합니다.

보기 추가

Views 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 > 새 폴더를 클릭하고 폴더의 이름을 HelloWorld로 지정합니다.

Views/HelloWorld 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 > 새 항목을 클릭합니다.

새 항목 추가 - MvcMovie 대화 상자에서 다음을 수행합니다.

  • 오른쪽 위의 검색 상자에 를 입력합니다.
  • Razor 뷰 - 비어 있음을 선택합니다.
  • 이름 상자 값을 Index.cshtml유지합니다.
  • 추가 선택

새 항목 추가 대화 상자

Views/HelloWorld/Index.cshtmlRazor 뷰 파일의 콘텐츠를 다음으로 바꿉니다.

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

https://localhost:{PORT}/HelloWorld로 이동합니다.

  • HelloWorldControllerIndex 메서드는 return View(); 문을 실행했습니다. 이 문은 메서드가 뷰 템플릿 파일을 사용하여 브라우저에 대한 응답을 렌더링해야 함을 지정합니다.

  • 뷰 템플릿 파일 이름을 지정하지 않았으므로 MVC는 기본 뷰 파일을 사용하도록 기본 설정되었습니다. 뷰 파일 이름을 지정하지 않으면 기본 뷰가 반환됩니다. 이 예제에서 기본 뷰는 작업 메서드 Index와 동일한 이름을 갖습니다. 보기 템플릿 /Views/HelloWorld/Index.cshtml 이 사용됩니다.

  • 다음 이미지는 뷰에서 하드 코드된 "Hello from our View Template!" 문자열을 보여 줍니다.

    브라우저 창

보기 및 레이아웃 페이지 변경

메뉴 링크 MvcMovie, Home, Privacy를 선택합니다. 각 페이지는 동일한 메뉴 레이아웃을 표시합니다. 메뉴 레이아웃은 파일에서 Views/Shared/_Layout.cshtml 구현됩니다.

Views/Shared/_Layout.cshtml 파일을 엽니다.

레이아웃 템플릿은 다음을 허용합니다.

  • 사이트의 HTML 컨테이너 레이아웃을 한 곳에 지정
  • 사이트의 여러 페이지에 HTML 컨테이너 레이아웃 적용

@RenderBody() 줄을 찾습니다. RenderBody는 사용자가 만드는 모든 보기 전용 페이지가 표시되는 자리 표시자이며 레이아웃 페이지에서 래핑됩니다. 예를 들어 Privacy 링크를 선택하는 경우 Views/Home/Privacy.cshtml 뷰는 RenderBody 메서드 내에서 렌더링됩니다.

Views/Shared/_Layout.cshtml 파일의 내용을 다음 태그로 대체합니다. 변경 내용이 강조 표시되어 있습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Movie App</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2020 - Movie App - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

위에 태그에서는 다음과 같은 변경을 수행했습니다.

  • 세 번 나오는 MvcMovieMovie App으로 변경했습니다.
  • 앵커 요소 <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">MvcMovie</a><a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>로 변경했습니다.

이 앱은 영역을 사용하지 않기 때문에 위의 태그에서 asp-area=""앵커 태그 도우미 특성 및 특성 값이 생략되었습니다.

참고: Movies 컨트롤러는 구현되지 않았습니다. 지금은 Movie App 링크가 작동하지 않습니다.

변경 내용을 저장하고 Privacy 링크를 선택합니다. 브라우저 탭의 제목에 Privacy Policy - MvcMovie 대신 Privacy Policy - Movie App이 표시됨을 확인합니다.

Privacy 탭

Home 링크를 선택합니다.

제목 및 앵커 텍스트에 Movie App이 표시됩니다. 레이아웃 템플릿은 한 번 변경되었으며 사이트의 모든 페이지에 새 링크 텍스트 및 새 제목이 반영됩니다.

Views/_ViewStart.cshtml 파일을 검사합니다.

@{
    Layout = "_Layout";
}

파일은 Views/_ViewStart.cshtml 각 보기에 Views/Shared/_Layout.cshtml 파일을 가져옵니다. Layout 속성을 사용하여 다른 레이아웃 보기를 설정하거나 레이아웃 파일을 사용하지 않도록 null로 설정할 수 있습니다.

Views/HelloWorld/Index.cshtml 뷰 파일을 엽니다.

다음에 강조 표시된 대로 제목과 <h2> 요소를 변경합니다.

@{
    ViewData["Title"] = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

제목과 <h2> 요소가 약간 다르기 때문에 코드의 어떤 부분에서 표시가 변경되는지가 명확합니다.

위의 코드에서 ViewData["Title"] = "Movie List";ViewData 사전의 Title 속성을 "Movie List"로 설정합니다. Title 속성은 레이아웃 페이지의 <title> HTML 요소에서 사용됩니다.

<title>@ViewData["Title"] - Movie App</title>

변경 내용을 저장하고 https://localhost:{PORT}/HelloWorld로 이동합니다.

다음 사항이 변경되었습니다.

  • 브라우저 제목
  • 기본 제목
  • 보조 제목

브라우저에 변경 내용이 없으면 보고 있는 캐시된 콘텐츠일 수 있습니다. 브라우저에서 Ctrl+F5를 눌러 서버의 응답이 강제로 로드되도록 합니다. 브라우저 제목은 Index.cshtml 뷰 템플릿에서 설정한 ViewData["Title"] 및 레이아웃 파일에 추가된 추가 “- Movie App”으로 만들어집니다.

보기 템플릿의 Index.cshtml 콘텐츠는 보기 템플릿과 Views/Shared/_Layout.cshtml 병합됩니다. 단일 HTML 응답이 브라우저로 전송되었습니다. 레이아웃 템플릿을 사용하면 응용 프로그램의 모든 페이지에 걸쳐 적용되는 변경 내용을 쉽게 만들 수 있습니다. 자세한 내용은 레이아웃을 참조하세요.

영화 목록 보기

그러나 작은 양의 "데이터"인 "Hello from our View Template!" 메시지는 하드 코드되어 있습니다. MVC 애플리케이션에는 “V”(뷰)와 “C”(컨트롤러)가 있지만 “M”(모델)은 아직 없습니다.

컨트롤러에서 보기로 데이터 전달

컨트롤러 작업은 들어오는 URL 요청에 대한 응답으로 호출됩니다. 컨트롤러 클래스는 들어오는 브라우저 요청을 처리하는 코드가 작성된 위치입니다. 컨트롤러는 데이터 원본에서 데이터를 검색하고 브라우저에 다시 전송할 응답의 유형을 결정합니다. 보기 템플릿은 브라우저에 대한 HTML 응답을 만들고 서식을 지정하기 위해서 컨트롤러에서 사용될 수 있습니다.

컨트롤러는 보기 템플릿에서 응답을 렌더링하기 위해 필요한 데이터를 제공할 책임이 있습니다.

뷰 템플릿은 다음을 수행하면 안 됩니다.

  • 비즈니스 논리 수행
  • 데이터베이스와 직접 상호 작용

뷰 템플릿은 컨트롤러에서 제공하는 데이터만 사용해야 합니다. 이 “문제의 분리”를 유지 관리하면 코드를 다음과 같이 유지할 수 있습니다.

  • 정리
  • 테스트 가능
  • 유지 관리 가능

현재 HelloWorldController 클래스에서 Welcome 메서드는 nameID 매개 변수를 가져온 다음, 값을 브라우저로 직접 출력합니다.

컨트롤러가 이 응답을 문자열로 렌더링하게 하는 대신, 보기 템플릿을 사용하도록 컨트롤러를 변경합니다. 보기 템플릿은 동적 응답을 생성합니다. 즉, 응답을 생성하려면 컨트롤러에서 뷰로 적절한 데이터를 전달해야 한다는 의미입니다. 컨트롤러가 뷰 템플릿에 필요한 동적 데이터(매개 변수)를 ViewData 사전에 넣도록 하면 됩니다. 그러면 뷰 템플릿이 동적 데이터에 액세스할 수 있습니다.

에서 HelloWorldController.cs메서드를 Welcome 변경하여 사전에 a MessageNumTimes 값을 ViewData 추가합니다.

ViewData 사전은 동적 개체로, 모든 형식을 사용할 수 있다는 의미입니다. ViewData 개체는 항목이 추가될 때까지 정의된 속성이 없습니다. MVC 모델 바인딩 시스템은 쿼리 문자열에서 메서드의 매개 변수로 명명된 매개 변수(namenumTimes)를 자동으로 매핑합니다. 완료된 HelloWorldController는 다음과 같습니다.

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
    public class HelloWorldController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Welcome(string name, int numTimes = 1)
        {
            ViewData["Message"] = "Hello " + name;
            ViewData["NumTimes"] = numTimes;

            return View();
        }
    }
}

ViewData 사전 개체는 보기에 전달될 데이터를 담고 있습니다.

라는 시작 보기 템플릿을 만듭니다 Views/HelloWorld/Welcome.cshtml.

Welcome.cshtml 뷰 템플릿에 “Hello” NumTimes를 표시하는 반복을 만듭니다. Views/HelloWorld/Welcome.cshtml의 내용을 다음으로 바꿉니다.

@{
    ViewData["Title"] = "Welcome";
}

<h2>Welcome</h2>

<ul>
    @for (int i = 0; i < (int)ViewData["NumTimes"]; i++)
    {
        <li>@ViewData["Message"]</li>
    }
</ul>

변경 내용을 저장하고 다음 URL로 이동합니다.

https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

데이터는 URL에서 가져와서 MVC 모델 바인더를 사용하여 컨트롤러에 전달됩니다. 컨트롤러는 데이터를 ViewData 사전으로 패키징하고 해당 개체를 보기에 전달합니다. 그런 다음 보기는 데이터를 HTML로 브라우저에 렌더링합니다.

Privacy 시작 레이블과 Hello Rick이 네 번 표시된 문구를 보여 주는 보기

위 샘플에서는 컨트롤러에서 뷰로 데이터를 전달하는 데 ViewData 사전이 사용되었습니다. 자습서의 뒷부분에서는 컨트롤러에서 보기로 데이터를 전달하기 위해 보기 모델이 사용됩니다. 데이터를 전달하는 뷰 모델 접근 방식이 ViewData 사전 접근 방식보다 선호됩니다.

다음 자습서에서는 영화 데이터베이스가 만들어집니다.

이 섹션에서는 Razor 뷰 파일을 사용하도록 HelloWorldController 클래스를 수정합니다. 그러면 클라이언트에 대한 HTML 응답을 생성하는 프로세스가 깔끔하게 캡슐화됩니다.

Razor를 사용하여 뷰 템플릿을 만듭니다. Razor 기반 뷰 템플릿은 다음과 같습니다.

  • 파일 확장명은 .cshtml입니다.
  • C#으로 HTML 출력을 만드는 세련된 방법을 제공합니다.

현재 Index 메서드는 컨트롤러 클래스에서 메시지와 함께 문자열을 반환합니다. HelloWorldController 클래스에서 Index 메서드를 다음 코드로 바꿉니다.

public IActionResult Index()
{
    return View();
}

앞의 코드가 하는 역할은 다음과 같습니다.

  • 컨트롤러의 View 메서드를 호출합니다.
  • 뷰 템플릿을 사용하여 HTML 응답을 생성합니다.

컨트롤러 메서드:

  • ‘작업 메서드’라고 합니다. 예를 들어 위의 코드에는 Index 작업 메서드가 있습니다.
  • 일반적으로 string 같은 형식이 아니라 ActionResult에서 파생된 클래스 또는 IActionResult를 반환합니다.

보기 추가

Views 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 > 새 폴더를 클릭하고 폴더의 이름을 HelloWorld로 지정합니다.

Views/HelloWorld 폴더를 마우스 오른쪽 단추로 클릭한 다음 추가 > 새 항목을 클릭합니다.

새 항목 추가 - MvcMovie 대화 상자에서 다음을 수행합니다.

  • 오른쪽 위의 검색 상자에 를 입력합니다.
  • Razor 뷰 - 비어 있음을 선택합니다.
  • 이름 상자 값을 Index.cshtml유지합니다.
  • 추가 선택

새 항목 추가 대화 상자

Views/HelloWorld/Index.cshtmlRazor 뷰 파일의 콘텐츠를 다음으로 바꿉니다.

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

https://localhost:{PORT}/HelloWorld로 이동합니다.

  • HelloWorldControllerIndex 메서드는 return View(); 문을 실행했습니다. 이 문은 메서드가 뷰 템플릿 파일을 사용하여 브라우저에 대한 응답을 렌더링해야 함을 지정합니다.

  • 뷰 템플릿 파일 이름을 지정하지 않았으므로 MVC는 기본 뷰 파일을 사용하도록 기본 설정되었습니다. 뷰 파일 이름을 지정하지 않으면 기본 뷰가 반환됩니다. 이 예제에서 기본 뷰는 작업 메서드 Index와 동일한 이름을 갖습니다. 보기 템플릿 /Views/HelloWorld/Index.cshtml 이 사용됩니다.

  • 다음 이미지는 뷰에서 하드 코드된 "Hello from our View Template!" 문자열을 보여 줍니다.

    브라우저 창

보기 및 레이아웃 페이지 변경

메뉴 링크 MvcMovie, Home, Privacy를 선택합니다. 각 페이지는 동일한 메뉴 레이아웃을 표시합니다. 메뉴 레이아웃은 파일에서 Views/Shared/_Layout.cshtml 구현됩니다.

Views/Shared/_Layout.cshtml 파일을 엽니다.

레이아웃 템플릿은 다음을 허용합니다.

  • 사이트의 HTML 컨테이너 레이아웃을 한 곳에 지정
  • 사이트의 여러 페이지에 HTML 컨테이너 레이아웃 적용

@RenderBody() 줄을 찾습니다. RenderBody는 사용자가 만드는 모든 보기 전용 페이지가 표시되는 자리 표시자이며 레이아웃 페이지에서 래핑됩니다. 예를 들어 Privacy 링크를 선택하는 경우 Views/Home/Privacy.cshtml 뷰는 RenderBody 메서드 내에서 렌더링됩니다.

Views/Shared/_Layout.cshtml 파일의 내용을 다음 태그로 대체합니다. 변경 내용이 강조 표시되어 있습니다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - Movie App</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2020 - Movie App - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
        </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @RenderSection("Scripts", required: false)
</body>
</html>

위에 태그에서는 다음과 같은 변경을 수행했습니다.

  • 세 번 나오는 MvcMovieMovie App으로 변경했습니다.
  • 앵커 요소 <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">MvcMovie</a><a class="navbar-brand" asp-controller="Movies" asp-action="Index">Movie App</a>로 변경했습니다.

이 앱은 영역을 사용하지 않기 때문에 위의 태그에서 asp-area=""앵커 태그 도우미 특성 및 특성 값이 생략되었습니다.

참고: Movies 컨트롤러는 구현되지 않았습니다. 지금은 Movie App 링크가 작동하지 않습니다.

변경 내용을 저장하고 Privacy 링크를 선택합니다. 브라우저 탭의 제목에 Privacy Policy - MvcMovie 대신 Privacy Policy - Movie App이 표시됨을 확인합니다.

Privacy 탭

Home 링크를 선택합니다.

제목 및 앵커 텍스트에 Movie App이 표시됩니다. 레이아웃 템플릿은 한 번 변경되었으며 사이트의 모든 페이지에 새 링크 텍스트 및 새 제목이 반영됩니다.

Views/_ViewStart.cshtml 파일을 검사합니다.

@{
    Layout = "_Layout";
}

파일은 Views/_ViewStart.cshtml 각 보기에 Views/Shared/_Layout.cshtml 파일을 가져옵니다. Layout 속성을 사용하여 다른 레이아웃 보기를 설정하거나 레이아웃 파일을 사용하지 않도록 null로 설정할 수 있습니다.

Views/HelloWorld/Index.cshtml 뷰 파일을 엽니다.

다음에 강조 표시된 대로 제목과 <h2> 요소를 변경합니다.

@{
    ViewData["Title"] = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

제목과 <h2> 요소가 약간 다르기 때문에 코드의 어떤 부분에서 표시가 변경되는지가 명확합니다.

위의 코드에서 ViewData["Title"] = "Movie List";ViewData 사전의 Title 속성을 "Movie List"로 설정합니다. Title 속성은 레이아웃 페이지의 <title> HTML 요소에서 사용됩니다.

<title>@ViewData["Title"] - Movie App</title>

변경 내용을 저장하고 https://localhost:{PORT}/HelloWorld로 이동합니다.

다음 사항이 변경되었습니다.

  • 브라우저 제목
  • 기본 제목
  • 보조 제목

브라우저에 변경 내용이 없으면 보고 있는 캐시된 콘텐츠일 수 있습니다. 브라우저에서 Ctrl+F5를 눌러 서버의 응답이 강제로 로드되도록 합니다. 브라우저 제목은 Index.cshtml 뷰 템플릿에서 설정한 ViewData["Title"] 및 레이아웃 파일에 추가된 추가 “- Movie App”으로 만들어집니다.

보기 템플릿의 Index.cshtml 콘텐츠는 보기 템플릿과 Views/Shared/_Layout.cshtml 병합됩니다. 단일 HTML 응답이 브라우저로 전송되었습니다. 레이아웃 템플릿을 사용하면 응용 프로그램의 모든 페이지에 걸쳐 적용되는 변경 내용을 쉽게 만들 수 있습니다. 자세한 내용은 레이아웃을 참조하세요.

영화 목록 보기

그러나 작은 양의 "데이터"인 "Hello from our View Template!" 메시지는 하드 코드되어 있습니다. MVC 애플리케이션에는 “V”(뷰)와 “C”(컨트롤러)가 있지만 “M”(모델)은 아직 없습니다.

컨트롤러에서 보기로 데이터 전달

컨트롤러 작업은 들어오는 URL 요청에 대한 응답으로 호출됩니다. 컨트롤러 클래스는 들어오는 브라우저 요청을 처리하는 코드가 작성된 위치입니다. 컨트롤러는 데이터 원본에서 데이터를 검색하고 브라우저에 다시 전송할 응답의 유형을 결정합니다. 보기 템플릿은 브라우저에 대한 HTML 응답을 만들고 서식을 지정하기 위해서 컨트롤러에서 사용될 수 있습니다.

컨트롤러는 보기 템플릿에서 응답을 렌더링하기 위해 필요한 데이터를 제공할 책임이 있습니다.

뷰 템플릿은 다음을 수행하면 안 됩니다.

  • 비즈니스 논리 수행
  • 데이터베이스와 직접 상호 작용

뷰 템플릿은 컨트롤러에서 제공하는 데이터만 사용해야 합니다. 이 “문제의 분리”를 유지 관리하면 코드를 다음과 같이 유지할 수 있습니다.

  • 정리
  • 테스트 가능
  • 유지 관리 가능

현재 HelloWorldController 클래스에서 Welcome 메서드는 nameID 매개 변수를 가져온 다음, 값을 브라우저로 직접 출력합니다.

컨트롤러가 이 응답을 문자열로 렌더링하게 하는 대신, 보기 템플릿을 사용하도록 컨트롤러를 변경합니다. 보기 템플릿은 동적 응답을 생성합니다. 즉, 응답을 생성하려면 컨트롤러에서 뷰로 적절한 데이터를 전달해야 한다는 의미입니다. 컨트롤러가 뷰 템플릿에 필요한 동적 데이터(매개 변수)를 ViewData 사전에 넣도록 하면 됩니다. 그러면 뷰 템플릿이 동적 데이터에 액세스할 수 있습니다.

에서 HelloWorldController.cs메서드를 Welcome 변경하여 사전에 a MessageNumTimes 값을 ViewData 추가합니다.

ViewData 사전은 동적 개체로, 모든 형식을 사용할 수 있다는 의미입니다. ViewData 개체는 항목이 추가될 때까지 정의된 속성이 없습니다. MVC 모델 바인딩 시스템은 쿼리 문자열에서 메서드의 매개 변수로 명명된 매개 변수(namenumTimes)를 자동으로 매핑합니다. 완료된 HelloWorldController는 다음과 같습니다.

using Microsoft.AspNetCore.Mvc;
using System.Text.Encodings.Web;

namespace MvcMovie.Controllers
{
    public class HelloWorldController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult Welcome(string name, int numTimes = 1)
        {
            ViewData["Message"] = "Hello " + name;
            ViewData["NumTimes"] = numTimes;

            return View();
        }
    }
}

ViewData 사전 개체는 보기에 전달될 데이터를 담고 있습니다.

라는 시작 보기 템플릿을 만듭니다 Views/HelloWorld/Welcome.cshtml.

Welcome.cshtml 뷰 템플릿에 “Hello” NumTimes를 표시하는 반복을 만듭니다. Views/HelloWorld/Welcome.cshtml의 내용을 다음으로 바꿉니다.

@{
    ViewData["Title"] = "Welcome";
}

<h2>Welcome</h2>

<ul>
    @for (int i = 0; i < (int)ViewData["NumTimes"]; i++)
    {
        <li>@ViewData["Message"]</li>
    }
</ul>

변경 내용을 저장하고 다음 URL로 이동합니다.

https://localhost:{PORT}/HelloWorld/Welcome?name=Rick&numtimes=4

데이터는 URL에서 가져와서 MVC 모델 바인더를 사용하여 컨트롤러에 전달됩니다. 컨트롤러는 데이터를 ViewData 사전으로 패키징하고 해당 개체를 보기에 전달합니다. 그런 다음 보기는 데이터를 HTML로 브라우저에 렌더링합니다.

Privacy 시작 레이블과 Hello Rick이 네 번 표시된 문구를 보여 주는 보기

위 샘플에서는 컨트롤러에서 뷰로 데이터를 전달하는 데 ViewData 사전이 사용되었습니다. 자습서의 뒷부분에서는 컨트롤러에서 보기로 데이터를 전달하기 위해 보기 모델이 사용됩니다. 데이터를 전달하는 뷰 모델 접근 방식이 ViewData 사전 접근 방식보다 선호됩니다.

다음 자습서에서는 영화 데이터베이스가 만들어집니다.