다음을 통해 공유


영화 컨트롤러에 대한 편집 작업 메서드 및 뷰 검사

작성자: Rick Anderson

참고 항목

이 자습서의 업데이트된 버전은 최신 버전의 Visual Studio를 사용하여 여기에서 사용할 수 있습니다. 새 자습서에서는 ASP.NET Core MVC를 사용하여 이 자습서를 통해 많은 개선 사항을 제공합니다.

이 자습서에서는 컨트롤러와 보기를 통해 ASP.NET Core MVC에 설명합니다. Razor Pages는 웹 UI 빌드를 더 쉽고 생산성 있게 만드는 페이지 기반 프로그래밍 모델인 ASP.NET Core의 새로운 대안입니다. MVC 버전 이전의 Razor 페이지 자습서를 사용해 보는 것이 좋습니다. Razor 페이지 자습서:

  • 자습서 내용을 좀 더 쉽게 진행할 수 있습니다.
  • 더 많은 기능을 다룹니다.
  • 새 앱 개발을 위한 기본 접근 방식입니다.

이 섹션에서는 영화 컨트롤러에 대해 생성된 Edit 작업 메서드 및 뷰를 살펴봅니다. 하지만 먼저 릴리스 날짜를 더 보기 좋게 만들기 위해 잠시 전환하겠습니다. Models\Movie.cs 파일을 열고 아래에 표시된 강조 표시된 줄을 추가합니다.

using System;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }
        public string Title { get; set; }

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }

    public class MovieDBContext : DbContext
    {
        public DbSet<Movie> Movies { get; set; }
    }
}

날짜 문화권을 다음과 같이 지정할 수도 있습니다.

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

다음 자습서에서 DataAnnotations를 다룰 예정입니다. Display 특성은 필드의 이름으로 표시할 내용을 지정합니다(이 경우 "ReleaseDate" 대신 "Release Date") DataType 특성은 데이터의 형식을 지정합니다. 이 경우 날짜이므로 필드에 저장된 시간 정보가 표시되지 않습니다. 날짜 형식을 잘못 렌더링하는 Chrome 브라우저의 버그에는 DisplayFormat 특성이 필요합니다.

애플리케이션을 실행하고 컨트롤러로 찾습니다 Movies . 마우스 포인터를 편집 링크 위에 놓으면 링크가 연결되는 URL을 볼 수 있습니다.

EditLink_sm

편집 링크는 Views\Movies\Index.cshtml 보기의 메서드에 의해 Html.ActionLink 생성되었습니다.

@Html.ActionLink("Edit", "Edit", new { id=item.ID })

Html.ActionLink

개체는 Html System.Web.Mvc.WebViewPage 기본 클래스의 속성을 사용하여 노출되는 도우미입니다. ActionLink 도우미 메서드를 사용하면 컨트롤러의 작업 메서드에 연결되는 HTML 하이퍼링크를 쉽게 동적으로 생성할 수 있습니다. 메서드의 ActionLink 첫 번째 인수는 렌더링할 링크 텍스트(예: <a>Edit Me</a>)입니다. 두 번째 인수는 호출할 작업 메서드의 이름입니다(이 경우 Edit 작업). 마지막 인수는 경로 데이터를 생성하는 익명 개체입니다(이 경우 ID는 4).

이전 이미지에 표시된 생성된 링크는 .입니다 http://localhost:1234/Movies/Edit/4. 기본 경로(App_Start\RouteConfig.cs 설정)는 URL 패턴을 {controller}/{action}/{id}사용합니다. 따라서 ASP.NET 매개 변수가 http://localhost:1234/Movies/Edit/4 4인 컨트롤러의 Movies 작업 메서드에 대한 요청 Edit 으로 변환 ID 됩니다. App_Start\RouteConfig.cs 파일에서 다음 코드를 검사합니다. MapRoute 메서드는 HTTP 요청을 올바른 컨트롤러 및 작업 메서드로 라우팅하고 선택적 ID 매개 변수를 제공하는 데 사용됩니다. MapRoute 메서드는 컨트롤러, 작업 메서드 및 경로 데이터가 지정된 URL을 생성하는 등의 ActionLink HtmlHelpers에서도 사용됩니다.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", 
            id = UrlParameter.Optional }
    );
}

쿼리 문자열을 사용하여 작업 메서드 매개 변수를 전달할 수도 있습니다. 예를 들어 URL http://localhost:1234/Movies/Edit?ID=3 은 3의 매개 변수 ID 를 컨트롤러의 Edit 작업 메서드에 전달합니다 Movies .

EditQueryString

컨트롤러를 Movies 엽니다. 두 Edit 가지 작업 메서드는 아래에 나와 있습니다.

// GET: /Movies/Edit/5
public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    Movie movie = db.Movies.Find(id);
    if (movie == null)
    {
        return HttpNotFound();
    }
    return View(movie);
}

// POST: /Movies/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for 
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Entry(movie).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(movie);
}

두 번째 Edit 작업 메서드 앞에 HttpPost 특성이 지정되어 있는 것에 유의하세요. 이 특성은 POST 요청에 대해서만 메서드의 Edit 오버로드를 호출할 수 있도록 지정합니다. 첫 번째 편집 메서드에 특성을 적용 HttpGet 할 수 있지만 기본값이므로 필요하지 않습니다. (특성을 메서드로 HttpGet 암시적으로 할당된 작업 메서드를 HttpGet 참조합니다.) Bind 특성은 해커가 데이터를 모델에 과도하게 게시하지 못하게 하는 또 다른 중요한 보안 메커니즘입니다. 변경하려는 바인딩 특성에만 속성을 포함해야 합니다. 초과 게시 보안 노트에서 초과 게시 및 바인딩 특성에 대해 읽을 수 있습니다. 이 자습서에 사용된 간단한 모델에서는 모델의 모든 데이터를 바인딩합니다. ValidateAntiForgeryToken 특성은 요청의 위조를 방지하는 데 사용되며 편집 보기 파일(Views\Movies\Edit.cshtml)에서 쌍을 @Html.AntiForgeryToken() 이루며 아래와 같습니다.

@model MvcMovie.Models.Movie

@{
    ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()    
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        @Html.ValidationSummary(true)
        @Html.HiddenFor(model => model.ID)

        <div class="form-group">
            @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title)
            </div>
        </div>

@Html.AntiForgeryToken() 는 컨트롤러의 메서드에서 일치해야 하는 숨겨진 양식 위조 방지 토큰을 Edit Movies 생성합니다. MVC의 XSRF/CSRF 방지 자습서에서 사이트 간 요청 위조(XSRF 또는 CSRF라고도 함)에 대해 자세히 확인할 수 있습니다.

이 메서드는 HttpGet Edit 동영상 ID 매개 변수를 사용하고 Entity Framework Find 메서드를 사용하여 동영상을 조회한 다음 선택한 동영상을 편집 보기로 반환합니다. 동영상을 찾을 수 없으면 HttpNotFound 가 반환됩니다. 스캐폴딩 시스템은 Edit 보기를 만들 때 Movie 클래스를 검토하고 클래스의 각 속성에 대해 <label><input> 요소를 렌더링하기 위한 코드를 만들었습니다. 다음 예제는 Visual Studio 스캐폴딩 시스템이 생성한 Edit 보기를 보여줍니다.

@model MvcMovie.Models.Movie

@{
    ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()    
    <div class="form-horizontal">
        <h4>Movie</h4>
        <hr />
        @Html.ValidationSummary(true)
        @Html.HiddenFor(model => model.ID)

        <div class="form-group">
            @Html.LabelFor(model => model.Title, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title)
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.ReleaseDate, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ReleaseDate)
                @Html.ValidationMessageFor(model => model.ReleaseDate)
            </div>
        </div>
        @*Genre and Price removed for brevity.*@        
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

뷰 템플릿 @model MvcMovie.Models.Movie 에 파일 맨 위에 문이 있는 방식을 확인합니다. 이렇게 하면 뷰 템플릿의 모델이 형식 Movie이 될 것으로 예상됩니다.

스캐폴드된 코드는 여러 도우미 메서드 를 사용하여 HTML 태그를 간소화합니다. 도우미는 Html.LabelFor 필드의 이름("Title", "ReleaseDate", "Genre" 또는 "Price")을 표시합니다. 도우미는 Html.EditorFor HTML <input> 요소를 렌더링합니다. 도우미는 Html.ValidationMessageFor 해당 속성과 연결된 유효성 검사 메시지를 표시합니다.

애플리케이션을 실행하고 /Movies URL로 이동합니다. Edit 링크를 클릭합니다. 브라우저에서 페이지의 소스를 봅니다. 양식 요소의 HTML은 다음과 같습니다.

<form action="/movies/Edit/4" method="post">
   <input name="__RequestVerificationToken" type="hidden" value="UxY6bkQyJCXO3Kn5AXg-6TXxOj6yVBi9tghHaQ5Lq_qwKvcojNXEEfcbn-FGh_0vuw4tS_BRk7QQQHlJp8AP4_X4orVNoQnp2cd8kXhykS01" />  <fieldset class="form-horizontal">
      <legend>Movie</legend>

      <input data-val="true" data-val-number="The field ID must be a number." data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="4" />

      <div class="control-group">
         <label class="control-label" for="Title">Title</label>
         <div class="controls">
            <input class="text-box single-line" id="Title" name="Title" type="text" value="GhostBusters" />
            <span class="field-validation-valid help-inline" data-valmsg-for="Title" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="control-group">
         <label class="control-label" for="ReleaseDate">Release Date</label>
         <div class="controls">
            <input class="text-box single-line" data-val="true" data-val-date="The field Release Date must be a date." data-val-required="The Release Date field is required." id="ReleaseDate" name="ReleaseDate" type="date" value="1/1/1984" />
            <span class="field-validation-valid help-inline" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="control-group">
         <label class="control-label" for="Genre">Genre</label>
         <div class="controls">
            <input class="text-box single-line" id="Genre" name="Genre" type="text" value="Comedy" />
            <span class="field-validation-valid help-inline" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="control-group">
         <label class="control-label" for="Price">Price</label>
         <div class="controls">
            <input class="text-box single-line" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" type="text" value="7.99" />
            <span class="field-validation-valid help-inline" data-valmsg-for="Price" data-valmsg-replace="true"></span>
         </div>
      </div>

      <div class="form-actions no-color">
         <input type="submit" value="Save" class="btn" />
      </div>
   </fieldset>
</form>

요소는 <input> /Movies/Edit URL에 게시하도록 특성이 설정된 HTML <form> 요소 action있습니다. 저장 단추를 클릭하면 양식 데이터가 서버에 게시됩니다. 두 번째 줄은 호출에 의해 생성된 숨겨진 XSRF 토큰을 보여 줍니다 @Html.AntiForgeryToken() .

POST 요청 처리

다음 목록은 Edit 작업 메서드의 HttpPost 버전을 보여줍니다.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="ID,Title,ReleaseDate,Genre,Price")] Movie movie)
{
    if (ModelState.IsValid)
    {
        db.Entry(movie).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(movie);
}

ValidateAntiForgeryToken 특성은 뷰의 호출에 의해 생성된 XSRF 토큰의 유효성을 @Html.AntiForgeryToken() 검사합니다.

ASP.NET MVC 모델 바인더는 게시된 양식 값을 사용하고 매개 변수로 전달되는 개체를 movie 만듭니다Movie. ModelState.IsValid 양식에 제출된 데이터를 사용하여 개체를 수정(편집 또는 업데이트)Movie할 수 있음을 확인합니다. 데이터가 유효한 경우 동영상 데이터는 (MovieDBContext인스턴스)의 컬렉션에 db저장 Movies 됩니다. 새 동영상 데이터는 메서드를 호출하여 데이터베이스에 SaveChanges MovieDBContext저장됩니다. 데이터를 저장한 후 코드는 사용자를 MoviesController 클래스의 Index 동작 메서드로 다시 전달하며, 여기에는 방금 수행한 변경 사항을 포함하여 동영상 컬렉션이 표시됩니다.

클라이언트 쪽 유효성 검사에서 필드 값이 유효하지 않다고 판단되는 즉시 오류 메시지가 표시됩니다. JavaScript를 사용하지 않도록 설정하면 클라이언트 쪽 유효성 검사가 비활성화됩니다. 그러나 서버는 게시된 값이 유효하지 않다는 것을 감지하고 양식 값이 오류 메시지와 함께 다시 표시됩니다.

유효성 검사는 자습서의 뒷부분에서 자세히 검사됩니다.

Edit.cshtml 보기 템플릿의 도우미는 Html.ValidationMessageFor 적절한 오류 메시지 표시를 처리합니다.

abcNotValid

모든 메서드는 HttpGet 비슷한 패턴을 따릅니다. 영화 개체(또는 개체의 경우 Index목록)를 가져와서 모델을 보기에 전달합니다. 메서드는 Create 빈 동영상 개체를 만들기 뷰에 전달합니다. 생성, 편집, 삭제 또는 어떤 식으로든 데이터를 수정하는 모든 메서드는 메서드의 HttpPost 오버로드에서 해당 작업을 수행합니다. HTTP GET 메서드에서 데이터를 수정하는 것은 보안 위험입니다. 블로그 게시물 항목 ASP.NET MVC 팁 #46 – 보안 허점을 만들기 때문에 링크 삭제를 사용하지 마세요. GET 메서드에서 데이터를 수정하면 HTTP 모범 사례 및 아키텍처 REST 패턴도 위반됩니다. 이 패턴은 GET 요청이 애플리케이션의 상태를 변경하지 않도록 지정합니다. 다시 말해 GET 작업 수행은 부작용 없이 안전하고 영속 데이터를 수정하지 않는 방법으로 이루어져야 합니다.

영어가 아닌 로캘에 대한 jQuery 유효성 검사

미국-영어 컴퓨터를 사용하는 경우 이 섹션을 건너뛰고 다음 자습서로 이동하면 됩니다. 이 자습서 의 Globalize 버전은 여기에서 다운로드할 수 있습니다. 국제화에 대한 훌륭한 두 부분의 자습서는 Nadeem의 ASP.NET MVC 5 국제화를 참조 하세요.

참고 항목

소수점 및 영어 이외의 날짜 형식에 쉼표(",")를 사용하는 영어 이외의 로캘에 대해 jQuery 유효성 검사를 지원하려면 사용할 Globalize.parseFloatglobalize.js 및 특정 문화권/globalize.cultures.js 파일(from https://github.com/jquery/globalize ) 및 JavaScript를 포함해야 합니다. NuGet에서 jQuery 영어 이외의 유효성 검사를 가져올 수 있습니다. (영어 로캘을 사용하는 경우 Globalize를 설치하지 마세요.)

  1. 도구 메뉴에서 NuGet 패키지 관리자 클릭한 다음 솔루션용 NuGet 패키지 관리를 클릭합니다.

    영어가 아닌 로캘에 대한 jQuery 유효성 검사를 시작하는 도구 메뉴의 스크린샷

  2. 왼쪽 창에서 찾아보기*를 선택합니다 .*(아래 이미지 참조)

  3. 입력 상자에 Globalize*를 입력합니다.

    전역화를 입력하는 입력 상자의 스크린샷.

    를 선택하고 jQuery.Validation.Globalize설치 MvcMovie 를 클릭합니다. Scripts\jquery.globalize\globalize.js 파일이 프로젝트에 추가됩니다. *Scripts\jquery.globalize\cultures* 폴더에는 많은 문화권 JavaScript 파일이 포함됩니다. 이 패키지를 설치하는 데 5분 정도 걸릴 수 있습니다.

    다음 코드는 Views\Movies\Edit.cshtml 파일에 대한 수정 사항을 보여 줍니다.

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")

<script src="~/Scripts/globalize/globalize.js"></script>
<script src="~/Scripts/globalize/cultures/globalize.culture.@(System.Threading.Thread.CurrentThread.CurrentCulture.Name).js"></script>
<script>
    $.validator.methods.number = function (value, element) {
        return this.optional(element) ||
            !isNaN(Globalize.parseFloat(value));
    }
    $(document).ready(function () {
        Globalize.culture('@(System.Threading.Thread.CurrentThread.CurrentCulture.Name)');
    });
</script>
<script>
    jQuery.extend(jQuery.validator.methods, {
        range: function (value, element, param) {
            //Use the Globalization plugin to parse the value
            var val = Globalize.parseFloat(value);
            return this.optional(element) || (
                val >= param[0] && val <= param[1]);
        }
    });
    $.validator.methods.date = function (value, element) {
        return this.optional(element) ||
            Globalize.parseDate(value) ||
            Globalize.parseDate(value, "yyyy-MM-dd");
    }
</script>
}

모든 편집 보기에서 이 코드를 반복하지 않도록 레이아웃 파일로 이동할 수 있습니다. 스크립트 다운로드를 최적화하려면 내 자습서 번들링 및 축소를 참조하세요.

자세한 내용은 ASP.NET MVC 3 국제화ASP.NET MVC 3 국제화 - 2부(NerdDinner)를 참조하세요.

임시 수정으로, 로캘에서 유효성 검사를 수행할 수 없는 경우 컴퓨터에서 미국 영어를 사용하도록 강제 적용하거나 브라우저에서 JavaScript를 사용하지 않도록 설정할 수 있습니다. 컴퓨터에서 미국 영어를 사용하도록 강제하기 위해 프로젝트 루트 web.config 파일에 세계화 요소를 추가할 수 있습니다. 다음 코드에서는 문화권이 영어로 설정된 세계화 요소를 미국.

<system.web>
    <globalization culture ="en-US" />
    <!--elements removed for clarity-->
  </system.web>

다음 자습서에서는 검색 기능을 구현합니다.