편집 메서드 및 편집 보기 검사(VB)
작성자: Rick Anderson
이 자습서에서는 무료 버전의 Microsoft Visual Studio인 Microsoft Visual Web Developer 2010 Express Service Pack 1을 사용하여 ASP.NET MVC 웹 애플리케이션을 빌드하는 기본 사항을 설명합니다. 시작하기 전에 아래에 나열된 필수 구성 요소를 설치했는지 확인합니다. 웹 플랫폼 설치 관리자 링크를 클릭하여 모두 설치할 수 있습니다. 또는 다음 링크를 사용하여 필수 구성 요소를 개별적으로 설치할 수 있습니다.
- Visual Studio Web Developer Express SP1 필수 구성 요소
- MVC 3 도구 업데이트 ASP.NET
- SQL Server Compact 4.0(런타임 + 도구 지원)
Visual Web Developer 2010 대신 Visual Studio 2010을 사용하는 경우 Visual Studio 2010 필수 구성 요소 링크를 클릭하여 필수 구성 요소를 설치합니다.
VB.NET 소스 코드가 있는 Visual Web Developer 프로젝트를 이 항목과 함께 사용할 수 있습니다. VB.NET 버전을 다운로드합니다. C#을 선호하는 경우 이 자습서의 C# 버전 으로 전환합니다.
이 섹션에서는 영화 컨트롤러에 대해 생성된 작업 메서드 및 뷰를 살펴봅니다. 그런 다음 사용자 지정 검색 페이지를 추가합니다.
애플리케이션을 실행하고 브라우저의 Movies
주소 표시줄에 있는 URL에 /Movies를 추가하여 컨트롤러로 이동합니다. 마우스 포인터를 편집 링크 위에 놓으면 링크가 연결되는 URL을 볼 수 있습니다.
편집 링크는 Views\Movies\Index.vbhtml 뷰의 메서드에 의해 Html.ActionLink
생성되었습니다.
@Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID}) |
Html
개체는 기본 클래스의 속성을 WebViewPage
사용하여 노출되는 도우미입니다. ActionLink
도우미 메서드를 사용하면 컨트롤러의 작업 메서드에 연결되는 HTML 하이퍼링크를 쉽게 동적으로 생성할 수 있습니다. 메서드의 ActionLink
첫 번째 인수는 렌더링할 링크 텍스트(예: <a>Edit Me</a>
)입니다. 두 번째 인수는 호출할 작업 메서드의 이름입니다. 마지막 인수는 경로 데이터를 생성하는 익명 개체입니다(이 경우 ID는 4).
이전 이미지에 표시된 생성된 링크는 .입니다 http://localhost:xxxxx/Movies/Edit/4
. 기본 경로는 URL 패턴을 {controller}/{action}/{id}
사용합니다. 따라서 ASP.NET 매개 변수가 http://localhost:xxxxx/Movies/Edit/4
4인 컨트롤러의 Movies
작업 메서드에 대한 요청 Edit
으로 변환 ID
됩니다.
쿼리 문자열을 사용하여 작업 메서드 매개 변수를 전달할 수도 있습니다. 예를 들어 URL http://localhost:xxxxx/Movies/Edit?ID=4
은 4의 매개 변수 ID
를 컨트롤러의 Edit
작업 메서드에 전달합니다 Movies
.
컨트롤러를 Movies
엽니다. 두 Edit
가지 작업 메서드는 아래에 나와 있습니다.
'
' GET: /Movies/Edit/5
Function Edit(id As Integer) As ViewResult
Dim movie As Movie = db.Movies.Find(id)
Return View(movie)
End Function
'
' POST: /Movies/Edit/5
<HttpPost()>
Function Edit(movie As Movie) As ActionResult
If ModelState.IsValid Then
db.Entry(movie).State = EntityState.Modified
db.SaveChanges()
Return RedirectToAction("Index")
End If
Return View(movie)
End Function
두 번째 Edit
작업 메서드 앞에 HttpPost
특성이 지정되어 있는 것에 유의하세요. 이 특성은 POST 요청에 대해서만 메서드의 Edit
오버로드를 호출할 수 있도록 지정합니다. 첫 번째 편집 메서드에 특성을 적용 HttpGet
할 수 있지만 기본값이므로 필요하지 않습니다. (특성을 메서드로 HttpGet
암시적으로 할당된 작업 메서드를 HttpGet
참조합니다.)
이 메서드는 HttpGet
Edit
동영상 ID 매개 변수를 사용하고 Entity Framework Find
메서드를 사용하여 동영상을 조회한 다음 선택한 동영상을 편집 보기로 반환합니다. 스캐폴딩 시스템은 Edit 보기를 만들 때 Movie
클래스를 검토하고 클래스의 각 속성에 대해 <label>
및 <input>
요소를 렌더링하기 위한 코드를 만들었습니다. 다음 예제에서는 생성된 편집 보기를 보여줍니다.
@ModelType MvcMovie.Movie
@Code
ViewData("Title") = "Edit"
End Code
<h2>Edit</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@Using Html.BeginForm()
@Html.ValidationSummary(True)
@<fieldset>
<legend>Movie</legend>
@Html.HiddenFor(Function(model) model.ID)
<div class="editor-label">
@Html.LabelFor(Function(model) model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(Function(model) model.Title)
@Html.ValidationMessageFor(Function(model) model.Title)
</div>
<div class="editor-label">
@Html.LabelFor(Function(model) model.ReleaseDate)
</div>
<div class="editor-field">
@Html.EditorFor(Function(model) model.ReleaseDate)
@Html.ValidationMessageFor(Function(model) model.ReleaseDate)
</div>
<div class="editor-label">
@Html.LabelFor(Function(model) model.Genre)
</div>
<div class="editor-field">
@Html.EditorFor(Function(model) model.Genre)
@Html.ValidationMessageFor(Function(model) model.Genre)
</div>
<div class="editor-label">
@Html.LabelFor(Function(model) model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(Function(model) model.Price)
@Html.ValidationMessageFor(Function(model) model.Price)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
End Using
<div>
@Html.ActionLink("Back to List", "Index")
</div>
뷰 템플릿 @ModelType MvcMovie.Models.Movie
에 파일 맨 위에 문이 있는 방식을 확인합니다. 이렇게 하면 뷰 템플릿의 모델이 형식 Movie
이 될 것으로 예상됩니다.
스캐폴드된 코드는 여러 도우미 메서드 를 사용하여 HTML 태그를 간소화합니다. 도우미는 Html.LabelFor
필드의 이름("Title", "ReleaseDate", "Genre" 또는 "Price")을 표시합니다. 도우미는 Html.EditorFor
HTML <input>
요소를 표시합니다. 도우미는 Html.ValidationMessageFor
해당 속성과 연결된 유효성 검사 메시지를 표시합니다.
애플리케이션을 실행하고 /Movies URL로 이동합니다. Edit 링크를 클릭합니다. 브라우저에서 페이지의 소스를 봅니다. 페이지의 HTML은 다음 예제와 같습니다. (명확성을 위해 메뉴 태그가 제외되었습니다.)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Edit</title>
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="/Scripts/modernizr-1.7.min.js" type="text/javascript"></script>
</head>
<body>
<div class="page">
<header>
<div id="title">
<h1>MVC Movie App</h1>
</div>
...
</header>
<section id="main">
<h2>Edit</h2>
<script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
<form action="/Movies/Edit/4" method="post"> <fieldset>
<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="editor-label">
<label for="Title">Title</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Title" name="Title" type="text" value="Rio Bravo" />
<span class="field-validation-valid" data-valmsg-for="Title" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="ReleaseDate">ReleaseDate</label>
</div>
<div class="editor-field">
<input class="text-box single-line" data-val="true" data-val-required="The ReleaseDate field is required."
id="ReleaseDate" name="ReleaseDate" type="text" value="4/15/1959 12:00:00 AM" />
<span class="field-validation-valid" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="Genre">Genre</label>
</div>
<div class="editor-field">
<input class="text-box single-line" id="Genre" name="Genre" type="text" value="Western" />
<span class="field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
</div>
<div class="editor-label">
<label for="Price">Price</label>
</div>
<div class="editor-field">
<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="9.99" />
<span class="field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</form>
<div>
<a href="/Movies">Back to List</a>
</div>
</section>
<footer>
</footer>
</div>
</body>
</html>
요소는 <input>
/Movies/Edit URL에 게시하도록 특성이 설정된 HTML <form>
요소 action
에 있습니다. 편집 단추를 클릭하면 양식 데이터가 서버에 게시됩니다.
POST 요청 처리
다음 목록은 Edit
작업 메서드의 HttpPost
버전을 보여줍니다.
'
' POST: /Movies/Edit/5
<HttpPost()>
Function Edit(movie As Movie) As ActionResult
If ModelState.IsValid Then
db.Entry(movie).State = EntityState.Modified
db.SaveChanges()
Return RedirectToAction("Index")
End If
Return View(movie)
End Function
ASP.NET 프레임워크 모델 바인더는 게시된 양식 값을 사용하고 매개 변수로 전달되는 개체를 movie
만듭니다Movie
. 코드의 체크 인은 ModelState.IsValid
양식에 제출된 데이터를 사용하여 개체를 수정 Movie
할 수 있는지 확인합니다. 데이터가 유효한 경우 코드는 영화 데이터를 인스턴스 컬렉션에 Movies
MovieDBContext
저장합니다. 그런 다음, 코드는 데이터베이스에 변경 내용을 유지하는 메서드MovieDBContext
를 SaveChanges
호출하여 새 동영상 데이터를 데이터베이스에 저장합니다. 데이터를 저장한 후 코드는 사용자를 클래스의 MoviesController
작업 메서드로 Index
리디렉션하여 업데이트된 동영상이 동영상 목록에 표시되도록 합니다.
게시된 값이 유효하지 않으면 양식에서 다시 표시됩니다. Edit.vbhtml 보기 템플릿의 도우미는 Html.ValidationMessageFor
적절한 오류 메시지 표시를 처리합니다.
로캘 에 대한 참고: 일반적으로 영어 이외의 로캘로 작업하는 경우 영어 이외의 로캘을 사용하여 MVC 3 유효성 검사 지원 ASP.NET 참조 하세요.
Edit 메서드를 보다 강력하게 만들기
스캐폴딩 시스템에서 생성된 메서드는 HttpGet
Edit
전달된 ID가 유효한지 확인하지 않습니다. 사용자가 URL(http://localhost:xxxxx/Movies/Edit
)에서 ID 세그먼트를 제거하면 다음 오류가 표시됩니다.
사용자는 데이터베이스에 없는 ID(예: http://localhost:xxxxx/Movies/Edit/1234
)를 전달할 수도 있습니다. 이 제한을 해결하기 위해 작업 메서드를 HttpGet
Edit
두 가지 변경하면 됩니다. 먼저 ID가 ID
명시적으로 전달되지 않은 경우 기본값이 0이 되도록 매개 변수를 변경합니다. 동영상 개체를 Find
보기 템플릿으로 반환하기 전에 메서드가 실제로 동영상을 찾았는지 확인할 수도 있습니다. 업데이트 Edit
된 메서드는 다음과 같습니다.
Public Function Edit(Optional ByVal id As Integer = 0) As ActionResult
Dim movie As Movie = db.Movies.Find(id)
If movie Is Nothing Then
Return HttpNotFound()
End If
Return View(movie)
End Function
동영상을 찾을 수 없으면 메서드가 HttpNotFound
호출됩니다.
모든 메서드는 HttpGet
비슷한 패턴을 따릅니다. 영화 개체(또는 개체의 경우 Index
목록)를 가져와서 모델을 보기에 전달합니다. 메서드는 Create
빈 동영상 개체를 만들기 뷰에 전달합니다. 생성, 편집, 삭제 또는 어떤 식으로든 데이터를 수정하는 모든 메서드는 메서드의 HttpPost
오버로드에서 해당 작업을 수행합니다. HTTP GET 메서드에서 데이터를 수정하는 것은 보안 위험입니다. GET 메서드에서 데이터를 수정하면 HTTP 모범 사례 및 아키텍처 REST 패턴도 위반됩니다. 이 패턴은 GET 요청이 애플리케이션의 상태를 변경하지 않도록 지정합니다. 즉, GET 작업을 수행하는 것은 부작용이 없는 안전한 작업이어야 합니다.
검색 방법 및 검색 보기 추가
이 섹션에서는 장르 또는 이름으로 영화를 검색할 수 있는 작업 메서드를 추가 SearchIndex
합니다. /Movies/SearchIndex URL을 사용하여 사용할 수 있습니다. 요청에는 사용자가 영화를 검색하기 위해 채울 수 있는 입력 요소가 포함된 HTML 양식이 표시됩니다. 사용자가 양식을 제출하면 작업 메서드는 사용자가 게시한 검색 값을 가져오고 값을 사용하여 데이터베이스를 검색합니다.
SearchIndex 양식 표시
먼저 기존 MoviesController
클래스에 SearchIndex
작업 메서드를 추가합니다. 이 메서드는 HTML 양식이 포함된 뷰를 반환합니다. 코드는 다음과 같습니다.
Public Function SearchIndex(ByVal searchString As String) As ActionResult
Dim movies = From m In db.Movies
Select m
If Not String.IsNullOrEmpty(searchString) Then
movies = movies.Where(Function(s) s.Title.Contains(searchString))
End If
Return View(movies)
End Function
메서드의 SearchIndex
첫 번째 줄은 다음 LINQ 쿼리를 만들어 영화를 선택합니다.
Dim movies = From m In db.Movies Select m
쿼리는 이 시점에서 정의되지만 데이터 저장소에 대해 아직 실행되지 않았습니다.
매개 변수에 searchString
문자열이 포함된 경우 영화 쿼리는 다음 코드를 사용하여 검색 문자열 값을 필터링하도록 수정됩니다.
String.IsNullOrEmpty(searchString)가 아닌 경우
movies = movies. Where(Function)s.Title.Contains(searchString))
End If
LINQ 쿼리는 정의될 때 또는 메서드를 호출 Where
OrderBy
하여 수정할 때 실행되지 않습니다. 대신 쿼리 실행이 지연됩니다. 즉, 실현된 값이 실제로 반복되거나 ToList
메서드가 호출될 때까지 식의 평가가 지연됩니다. 샘플에서 SearchIndex
쿼리는 SearchIndex 보기에서 실행됩니다. 지연된 쿼리 실행에 대한 자세한 내용은 쿼리 실행을 참조하세요.
이제 사용자에게 양식을 표시할 보기를 구현 SearchIndex
할 수 있습니다. 메서드 내부를 마우스 오른쪽 단추로 SearchIndex
클릭한 다음 보기 추가를 클릭합니다. 보기 추가 대화 상자에서 개체를 뷰 템플릿에 모델 클래스로 전달 Movie
하도록 지정합니다. 스캐폴드 템플릿 목록에서 목록을 선택한 다음 추가를 클릭합니다.
추가 단추를 클릭하면 Views\Movies\SearchIndex.vbhtml 보기 템플릿이 만들어집니다. 스캐폴드 템플릿 목록에서 목록을 선택했기 때문에 Visual Web Developer는 보기에서 일부 기본 콘텐츠를 자동으로 생성(스캐폴드)했습니다. 스캐폴딩에서 HTML 양식을 만들었습니다. 클래스를 검사하고 클래스의 Movie
각 속성에 대한 요소를 렌더링 <label>
하는 코드를 만들었습니다. 아래 목록에는 생성된 만들기 보기가 표시됩니다.
@ModelType IEnumerable(Of MvcMovie.Movie)
@Code
ViewData("Title") = "SearchIndex"
End Code
<h2>SearchIndex</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Title
</th>
<th>
ReleaseDate
</th>
<th>
Genre
</th>
<th>
Price
</th>
<th></th>
</tr>
@For Each item In Model
Dim currentItem = item
@<tr>
<td>
@Html.DisplayFor(Function(modelItem) currentItem.Title)
</td>
<td>
@Html.DisplayFor(Function(modelItem) currentItem.ReleaseDate)
</td>
<td>
@Html.DisplayFor(Function(modelItem) currentItem.Genre)
</td>
<td>
@Html.DisplayFor(Function(modelItem) currentItem.Price)
</td>
<td>
@Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID}) |
@Html.ActionLink("Details", "Details", New With {.id = currentItem.ID}) |
@Html.ActionLink("Delete", "Delete", New With {.id = currentItem.ID})
</td>
</tr>
Next
</table>
애플리케이션을 실행하고 /Movies/SearchIndex로 이동합니다. 쿼리 문자열(예: ?searchString=ghost
)을 URL에 추가합니다. 필터링된 동영상이 표시됩니다.
메서드의 SearchIndex
시그니처를 이름이 지정된 id
id
매개 변수로 변경하면 매개 변수가 Global.asax 파일에 설정된 기본 경로의 자리 표시자와 일치 {id}
합니다.
{controller}/{action}/{id}
수정된 SearchIndex
메서드는 다음과 같습니다.
Public Function SearchIndex(ByVal id As String) As ActionResult
Dim searchString As String = id
Dim movies = From m In db.Movies
Select m
If Not String.IsNullOrEmpty(searchString) Then
movies = movies.Where(Function(s) s.Title.Contains(searchString))
End If
Return View(movies)
End Function
이제 쿼리 문자열 값 대신 경로 데이터(URL 세그먼트)로 검색 제목을 전달할 수 있습니다.
그러나 사용자가 영화를 검색하려고 할 때마다 URL을 수정하지는 않습니다. 이제 영화를 필터링하는 데 도움이 되는 UI를 추가합니다. 경로 바인딩 ID 매개 변수를 전달하는 방법을 테스트하기 위해 메서드의 SearchIndex
서명을 변경한 경우 메서드가 SearchIndex
다음과 같은 searchString
문자열 매개 변수를 사용하도록 다시 변경합니다.
Views\Movies\SearchIndex.vbhtml 파일을 열고 바로 다음에 @Html.ActionLink("Create New", "Create")
다음을 추가합니다.
@Code
ViewData("Title") = "SearchIndex"
Using (Html.BeginForm())
@<p> Title: @Html.TextBox("SearchString")
<input type="submit" value="Filter" /></p>
End Using
End Code
도우미가 여 <form>
는 Html.BeginForm
태그를 만듭니다. Html.BeginForm
사용자가 필터 단추를 클릭하여 양식을 제출할 때 도우미가 양식 자체에 게시되도록 합니다.
애플리케이션을 실행하고 동영상을 검색해 봅니다.
메서드의 오버로드가 SearchIndex
없습니다HttpPost
. 메서드가 애플리케이션의 상태를 변경하지 않고 데이터를 필터링하기 때문에 필요하지 않습니다. 다음 HttpPost
SearchIndex
메서드를 추가한 경우 작업 호출자는 메서드와 일치 SearchIndex
HttpPost
하며 메서드는 HttpPost
SearchIndex
아래 이미지와 같이 실행됩니다.
<HttpPost()>
Public Function SearchIndex(ByVal fc As FormCollection, ByVal searchString As String) As String
Return "<h3> From [HttpPost]SearchIndex: " & searchString & "</h3>"
End Function
장르별 검색 추가
메서드 버전을 SearchIndex
추가한 HttpPost
경우 지금 삭제합니다.
다음으로 사용자가 장르별로 영화를 검색할 수 있도록 하는 기능을 추가합니다. SearchIndex
메서드를 다음 코드로 바꿉니다.
Public Function SearchIndex(ByVal movieGenre As String, ByVal searchString As String) As ActionResult
Dim GenreLst = New List(Of String)()
Dim GenreQry = From d In db.Movies
Order By d.Genre
Select d.Genre
GenreLst.AddRange(GenreQry.Distinct())
ViewBag.movieGenre = New SelectList(GenreLst)
Dim movies = From m In db.Movies
Select m
If Not String.IsNullOrEmpty(searchString) Then
movies = movies.Where(Function(s) s.Title.Contains(searchString))
End If
If String.IsNullOrEmpty(movieGenre) Then
Return View(movies)
Else
Return View(movies.Where(Function(x) x.Genre = movieGenre))
End If
End Function
이 버전의 메서드는 SearchIndex
추가 매개 변수, 즉 movieGenre
. 처음 몇 줄의 코드는 데이터베이스에서 영화 장르를 저장할 개체를 만듭니 List
다.
다음 코드는 데이터베이스에서 모든 장르를 검색하는 LINQ 쿼리입니다.
Dim GenreQry = From d In db.Movies
Order By d.Genre
Select d.Genre
이 코드는 제네릭 List
컬렉션의 메서드를 사용하여 AddRange
목록에 모든 고유 장르를 추가합니다. (한정자가 없으면 Distinct
중복된 장르가 추가됩니다. 예를 들어 샘플에서 코미디가 두 번 추가됩니다). 그런 다음, 코드는 개체에 ViewBag
장르 목록을 저장합니다.
다음 코드는 매개 변수를 확인하는 movieGenre
방법을 보여줍니다. 비어 있지 않은 경우 코드는 영화 쿼리를 제한하여 선택한 영화를 지정된 장르로 제한합니다.
If String.IsNullOrEmpty(movieGenre) Then
Return View(movies)
Else
Return View(movies.Where(Function(x) x.Genre = movieGenre))
End If
SearchIndex 보기에 태그를 추가하여 장르별 검색 지원
Html.DropDownList
도우미 바로 앞에 Views\Movies\SearchIndex.vbhtml 파일에 도우미를 TextBox
추가합니다. 완료된 태그는 다음과 같습니다.
<p>
@Html.ActionLink("Create New", "Create")
@Code
ViewData("Title") = "SearchIndex"
Using (Html.BeginForm())
@<p> Genre: @Html.DropDownList("movieGenre", "All")
Title: @Html.TextBox("SearchString")
<input type="submit" value="Filter" /></p>
End Using
End Code
</p>
애플리케이션을 실행하고 /Movies/SearchIndex로 찾습니다. 장르, 영화 이름 및 두 기준별로 검색을 시도합니다.
이 섹션에서는 프레임워크에서 생성된 CRUD 작업 메서드 및 뷰를 검사했습니다. 사용자가 영화 제목 및 장르별로 검색할 수 있도록 하는 검색 작업 방법 및 보기를 만들었습니다. 다음 섹션에서는 모델에 속성을 추가하는 방법과 테스트 데이터베이스를 Movie
자동으로 만드는 이니셜라이저를 추가하는 방법을 살펴보겠습니다.