다음을 통해 공유


ASP.NET DropDownList 도우미를 스캐폴드하는 방법 검사

작성자 : Rick Anderson

솔루션 탐색기Controllers 폴더를 마우스 오른쪽 단추로 클릭한 다음 컨트롤러 추가를 선택합니다. 컨트롤러 이름을 StoreManagerController로 지정합니다. 아래 이미지와 같이 컨트롤러 추가 대화 상자의 옵션을 설정합니다.

솔루션 탐색기 컨트롤러 추가 대화 상자의 이미지

StoreManager\Index.cshtml 뷰를 편집하고 를 제거AlbumArtUrl합니다. 제거하면 AlbumArtUrl 프레젠테이션을 더 쉽게 읽을 수 있습니다. 완성된 코드는 다음과 같습니다.

@model IEnumerable<MvcMusicStore.Models.Album>

@{

    ViewBag.Title = "Index";

}

<h2>Index</h2>

<p>

    @Html.ActionLink("Create New", "Create")

</p>

<table>

    <tr>

        <th>

            Genre

        </th>

        <th>

            Artist

        </th>

        <th>

            Title

        </th>

        <th>

            Price

        </th>

        <th></th>

    </tr>

@foreach (var item in Model) {

    <tr>

        <td>

            @Html.DisplayFor(modelItem => item.Genre.Name)

        </td>

        <td>

            @Html.DisplayFor(modelItem => item.Artist.Name)

        </td>

        <td>

            @Html.DisplayFor(modelItem => item.Title)

        </td>

        <td>

            @Html.DisplayFor(modelItem => item.Price)

        </td>

        <td>

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

            @Html.ActionLink("Details", "Details", new { id=item.AlbumId }) |

            @Html.ActionLink("Delete", "Delete", new { id=item.AlbumId })

        </td>

    </tr>

}

</table>

Controllers\StoreManagerController.cs 파일을 열고 메서드를 찾습니다Index. 앨범이 OrderBy 가격별로 정렬되도록 절을 추가합니다. 전체 코드는 다음과 같습니다.

public ViewResult Index()
{

    var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist)

        .OrderBy(a => a.Price);

    return View(albums.ToList());

}

가격별로 정렬하면 데이터베이스 변경 내용을 더 쉽게 테스트할 수 있습니다. 편집 및 만들기 메서드를 테스트할 때 저장된 데이터가 먼저 표시되도록 저렴한 가격을 사용할 수 있습니다.

StoreManager\Edit.cshtml 파일을 엽니다. 범례 태그 바로 다음에 다음 줄을 추가합니다.

@Html.HiddenFor(model => model.AlbumId)

다음 코드는 이 변경의 컨텍스트를 보여줍니다.

@using (Html.BeginForm()) {

    @Html.ValidationSummary(true)

    <fieldset>

        <legend>Album</legend>

        @Html.HiddenFor(model => model.AlbumId)

        <div class="editor-label">

            @Html.LabelFor(model => model.GenreId, "Genre")

        </div>

        <div class="editor-field">

            @Html.DropDownList("GenreId", String.Empty)

            @Html.ValidationMessageFor(model => model.GenreId)

        </div>

        <!-- Items removed for brevity. -->

}

AlbumId 앨범 레코드를 변경하는 데 필요합니다.

Ctrl+F5를 눌러 애플리케이션을 실행합니다. 관리 링크를 선택한 다음 새로 만들기 링크를 선택하여 새 앨범을 만듭니다. 앨범 정보가 저장되었는지 확인합니다. 앨범을 편집하고 변경 내용이 유지되는지 확인합니다.

앨범 스키마

StoreManager MVC 스캐폴딩 메커니즘에서 만든 컨트롤러를 사용하면 음악 저장소 데이터베이스의 앨범에 CRUD(만들기, 읽기, 업데이트, 삭제)에 액세스할 수 있습니다. 앨범 정보에 대한 스키마는 다음과 같습니다.

앨범 스키마 이미지

테이블은 Albums 앨범 장르와 설명을 저장하지 않고 테이블에 외래 키를 Genres 저장합니다. 테이블에는 Genres 장르 이름과 설명이 포함됩니다. 마찬가지로 테이블에는 Albums 앨범 아티스트 이름이 아니라 테이블의 외래 키가 Artists 포함됩니다. 테이블에는 Artists 아티스트의 이름이 포함됩니다. 테이블의 데이터를 Albums 검사하면 각 행에 테이블에 대한 외래 키 Genres 와 테이블에 대한 외래 키가 포함되어 있는 것을 Artists 볼 수 있습니다. 아래 이미지는 테이블의 Albums 일부 테이블 데이터를 보여줍니다.

앨범 테이블의 일부 데이터 이미지

HTML 태그 선택

HTML <select> 요소(HTML DropDownList 도우미에서 생성됨)는 전체 값 목록(예: 장르 목록)을 표시하는 데 사용됩니다. 양식 편집의 경우 현재 값이 알려진 경우 선택 목록에서 현재 값을 표시할 수 있습니다. 이전에 선택한 값을 코미디로 설정했을 때 이 것을 보았습니다. 선택 목록은 범주 또는 외래 키 데이터를 표시하는 데 적합합니다. <select> Genre 외래 키의 요소는 가능한 장르 이름 목록을 표시하지만 폼을 저장하면 Genre 속성이 표시된 장르 이름이 아닌 Genre 외래 키 값으로 업데이트됩니다. 아래 이미지에서 선택한 장르는 디스코 이고 아티스트는 도나 서머입니다.

디스코 선택한 장르의 이미지

ASP.NET MVC 스캐폴드 코드 검사

Controllers\StoreManagerController.cs 파일을 열고 메서드를 찾습니다HTTP GET Create.

public ActionResult Create()

{

    ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name");

    ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");

    return View();

}

메서드는 Create개의 SelectList 개체를 ViewBag에 추가하고, 하나는 장르 정보를 포함하고, 다른 하나는 아티스트 정보를 포함합니다. 위에서 사용한 SelectList 생성자 오버로드는 다음 세 가지 인수를 사용합니다.

public SelectList(

    IEnumerable items,

    string dataValueField,

    string dataTextField

)
  1. items: 목록의 항목을 포함하는 IEnumerable 입니다. 위의 예제에서 에서 반환 db.Genres된 장르 목록입니다.
  2. dataValueField: 키 값을 포함하는 IEnumerable 목록에 있는 속성의 이름입니다. 위의 GenreId 예제에서 및 입니다 ArtistId.
  3. dataTextField: 표시할 정보가 포함된 IEnumerable 목록에 있는 속성의 이름입니다. 아티스트와 장르 테이블 모두에서 필드가 name 사용됩니다.

Views\StoreManager\Create.cshtml 파일을 열고 장르 필드에 대한 도우미 태그를 검사 Html.DropDownList 합니다.

@model MvcMusicStore.Models.Album

@*        Markup removed for clarity.*@

@Html.DropDownList("GenreId", String.Empty)

첫 번째 줄은 만들기 뷰가 모델을 사용하는 것을 Album 보여줍니다. Create 위에 표시된 메서드에서 모델이 전달되지 않았기 때문에 뷰는 nullAlbum 모델을 가져옵니다. 이 시점에서 우리는 그것에 대한 데이터가 없 Album 도록 새 앨범을 만들고 있습니다.

위에 표시된 Html.DropDownList 오버로드는 모델에 바인딩할 필드의 이름을 사용합니다. 또한 이 이름을 사용하여 SelectList 개체가 포함된 ViewBag 개체를 찾습니다. 이 오버로드를 사용하여 ViewBag SelectList 개체 GenreId의 이름을 로 지정해야 합니다. 두 번째 매개 변수(String.Empty)는 항목이 선택되지 않은 경우 표시할 텍스트입니다. 이것이 바로 새 앨범을 만들 때 우리가 원하는 것입니다. 두 번째 매개 변수를 제거하고 다음 코드를 사용한 경우:

@Html.DropDownList("GenreId")

선택 목록은 기본적으로 첫 번째 요소 또는 샘플의 Rock으로 설정됩니다.

기본 첫 번째 요소의 이미지

메서드를 검사합니다 HTTP POST Create .

//

// POST: /StoreManager/Create

[HttpPost]

public ActionResult Create(Album album)

{

    if (ModelState.IsValid)

    {

        db.Albums.Add(album);

        db.SaveChanges();

        return RedirectToAction("Index");  

    }

    ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name",

        album.GenreId);

    ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name",

        album.ArtistId);

    return View(album);

}

메서드의 Create 이 오버로드는 게시된 양식 값에서 ASP.NET MVC 모델 바인딩 시스템에서 만든 개체를 사용합니다 album . 새 앨범을 제출할 때 모델 상태가 유효하고 데이터베이스 오류가 없는 경우 새 앨범이 데이터베이스에 추가됩니다. 다음 이미지는 새 앨범의 생성을 보여줍니다.

새 앨범 만들기를 보여 주는 이미지

fiddler 도구를 사용하여 MVC 모델 바인딩이 앨범 개체를 만드는 데 사용하는 ASP.NET 게시된 양식 값을 검사할 수 있습니다.

Fiddler 도구의 이미지입니다.

ViewBag SelectList 만들기 리팩터링

Edit 메서드와 HTTP POST Create 메서드에는 모두 ViewBag에서 SelectList를 설정하는 동일한 코드가 있습니다. DRY의 정신으로 이 코드를 리팩터링합니다. 나중에 이 리팩터링된 코드를 사용할 것입니다.

장르 및 아티스트 SelectListViewBag에 추가하는 새 메서드를 만듭니다.

private void SetGenreArtistViewBag(int? GenreID = null, int? ArtistID = null) {

    if (GenreID == null)

        ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name");

    else

        ViewBag.GenreId = new SelectList(db.Genres.ToArray(), "GenreId", "Name", GenreID);

    if (ArtistID == null)

        ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");

    else

        ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", ArtistID);

}

CreateEdit 메서드에서 를 ViewBag 설정하는 두 줄을 메서드에 대한 호출 SetGenreArtistViewBag 로 바꿉 있습니다. 완성된 코드는 다음과 같습니다.

//

// GET: /StoreManager/Create

public ActionResult Create() {

    SetGenreArtistViewBag();

    return View();

}

//

// POST: /StoreManager/Create

[HttpPost]

public ActionResult Create(Album album) {

    if (ModelState.IsValid) {

        db.Albums.Add(album);

        db.SaveChanges();

        return RedirectToAction("Index");

    }

    SetGenreArtistViewBag(album.GenreId, album.ArtistId);

    return View(album);

}

//

// GET: /StoreManager/Edit/5

public ActionResult Edit(int id) {

    Album album = db.Albums.Find(id);

    SetGenreArtistViewBag(album.GenreId, album.ArtistId);

    return View(album);

}

//

// POST: /StoreManager/Edit/5

[HttpPost]

public ActionResult Edit(Album album) {

    if (ModelState.IsValid) {

        db.Entry(album).State = EntityState.Modified;

        db.SaveChanges();

        return RedirectToAction("Index");

    }

    SetGenreArtistViewBag(album.GenreId, album.ArtistId);

    return View(album);

}

새 앨범을 만들고 앨범을 편집하여 변경 내용이 작동하는지 확인합니다.

SelectList를 DropDownList에 명시적으로 전달

ASP.NET MVC 스캐폴딩에서 만든 뷰 만들기 및 편집은 다음 DropDownList 오버로드를 사용합니다.

public static MvcHtmlString DropDownList(

    this HtmlHelper htmlHelper,

    string name,         // The name of the ViewModel property to bind.

    string optionLabel   // The string added to the top of the list

                         // typically  String.Empty or "Select a Genre"

)

DropDownList 만들기 보기에 대한 태그는 다음과 같습니다.

@Html.DropDownList("GenreId", String.Empty)

의 속성 SelectList 이름이 ViewBagGenreId이므로 DropDownList 도우미는 ViewBag에서 GenreIdSelectList를 사용합니다. 다음 DropDownList 오버로드 SelectList 에서 는 명시적으로 전달됩니다.

public static MvcHtmlString DropDownList(

    this HtmlHelper htmlHelper,

    string name,            // The name of the ViewModel property to bind.

    IEnumerable selectList  // The SelectList

)

Views\StoreManager\Edit.cshtml 파일을 열고 DropDownList 호출을 변경하여 위의 오버로드를 사용하여 SelectList에 명시적으로 전달합니다. 장르 범주에 대해 이 작업을 수행합니다. 완성된 코드는 다음과 같습니다.

@Html.DropDownList("GenreId", ViewBag.GenreId as SelectList)

애플리케이션을 실행하고 관리 링크를 클릭한 다음 Jazz 앨범으로 이동하여 편집 링크를 선택합니다.

편집할 재즈 앨범 선택 이미지

현재 선택된 장르로 재즈를 표시하는 대신 록이 표시됩니다. 문자열 인수(바인딩할 속성)와 SelectList 개체의 이름이 같으면 선택한 값이 사용되지 않습니다. 선택한 값이 제공되지 않으면 브라우저는 기본적으로 SelectList의 첫 번째 요소(위의 예제에서는 Rock 임)로 설정됩니다. DropDownList 도우미의 알려진 제한 사항입니다.

Controllers\StoreManagerController.cs 파일을 열고 SelectList 개체 이름을 및 ArtistsGenres 변경합니다. 완성된 코드는 다음과 같습니다.

private void SetGenreArtistViewBag(int? GenreID = null, int? ArtistID = null) {
    if (GenreID == null)

        ViewBag.Genres = new SelectList(db.Genres, "GenreId", "Name");

    else

        ViewBag.Genres = new SelectList(db.Genres.ToArray(), "GenreId", "Name", GenreID);

    if (ArtistID == null)

        ViewBag.Artists = new SelectList(db.Artists, "ArtistId", "Name");

    else

        ViewBag.Artists = new SelectList(db.Artists, "ArtistId", "Name", ArtistID);

}

장르 및 아티스트 이름은 각 범주의 ID 이상을 포함하므로 범주에 더 적합한 이름입니다. 우리가 이전에 한 리팩터링이 성과를 냈다. 네 가지 메서드로 ViewBag 을 변경하는 대신 변경 내용이 메서드로 SetGenreArtistViewBag 격리되었습니다.

만들기 및 편집 보기에서 DropDownList 호출을 변경하여 새 SelectList 이름을 사용합니다. 편집 보기에 대한 새 태그는 다음과 같습니다.

<div class="editor-label">

    @Html.LabelFor(model => model.GenreId, "Genre")

</div>

<div class="editor-field">

    @Html.DropDownList("GenreId", ViewBag.Genres as SelectList)

    @Html.ValidationMessageFor(model => model.GenreId)

</div>

<div class="editor-label">

    @Html.LabelFor(model => model.ArtistId, "Artist")

</div>

<div class="editor-field">

    @Html.DropDownList("ArtistId", ViewBag.Artists as SelectList)

    @Html.ValidationMessageFor(model => model.ArtistId)

</div>

만들기 보기에는 SelectList의 첫 번째 항목이 표시되지 않도록 빈 문자열이 필요합니다.

<div class="editor-label">

    @Html.LabelFor(model => model.GenreId, "Genre" )

</div>

<div class="editor-field">

    @Html.DropDownList("GenreId", ViewBag.Genres as SelectList, String.Empty)

    @Html.ValidationMessageFor(model => model.GenreId)

</div>

<div class="editor-label">

    @Html.LabelFor(model => model.ArtistId, "Artist")

</div>

<div class="editor-field">

    @Html.DropDownList("ArtistId", ViewBag.Artists as SelectList, String.Empty)

    @Html.ValidationMessageFor(model => model.ArtistId)

</div>

새 앨범을 만들고 앨범을 편집하여 변경 내용이 작동하는지 확인합니다. Rock 이외의 장르가 있는 앨범을 선택하여 편집 코드를 테스트합니다.

DropDownList 도우미와 함께 보기 모델 사용

라는 ViewModels 폴더 AlbumSelectListViewModel에 새 클래스를 만듭니다. 클래스의 코드를 AlbumSelectListViewModel 다음으로 바꿉다.

using MvcMusicStore.Models;

using System.Web.Mvc;

using System.Collections;

namespace MvcMusicStore.ViewModels {

    public class AlbumSelectListViewModel {

        public Album Album { get; private set; }

        public SelectList Artists { get; private set; }

        public SelectList Genres { get; private set; }

        public AlbumSelectListViewModel(Album album, 

                                        IEnumerable artists, 

                                        IEnumerable genres) {

            Album = album;

            Artists = new SelectList(artists, "ArtistID", "Name", album.ArtistId);

            Genres = new SelectList(genres, "GenreID", "Name", album.GenreId);

        }

    }

}

AlbumSelectListViewModel 생성자는 앨범, 아티스트 및 장르 목록을 가져와 앨범 SelectList 과 장르 및 아티스트를 포함하는 개체를 만듭니다.

다음 단계에서 뷰를 만들 때 를 사용할 수 있도록 AlbumSelectListViewModel 프로젝트를 빌드합니다.

EditVM 메서드를 추가합니다 StoreManagerController. 완성된 코드는 다음과 같습니다.

//

// GET: /StoreManager/EditVM/5

public ActionResult EditVM(int id) {

    Album album = db.Albums.Find(id);

    if (album == null)

        return HttpNotFound();

    AlbumSelectListViewModel aslvm = new AlbumSelectListViewModel(album, db.Artists, db.Genres);

    return View(aslvm);

}

을 마우스 오른쪽 단추로 클릭하고 AlbumSelectListViewModel해결을 선택한 다음 MvcMusicStore.ViewModels;를 사용합니다.

resolve 선택하는 이미지

또는 다음 using 문을 추가할 수 있습니다.

using MvcMusicStore.ViewModels;

마우스 오른쪽 단추를 클릭하고 EditVM보기 추가를 선택합니다. 아래에 표시된 옵션을 사용합니다.

보기 추가 대화 상자를 보여 주는 이미지

추가를 선택한 다음 Views\StoreManager\EditVM.cshtml 파일의 내용을 다음으로 바꿉니다.

@model MvcMusicStore.ViewModels.AlbumSelectListViewModel

@{

    ViewBag.Title = "EditVM";

}

<h2>Edit VM</h2>

@using (Html.BeginForm("Edit","StoreManager",FormMethod.Post)) {

    @Html.ValidationSummary(true)

    <fieldset>

        <legend>Album</legend>

        @Html.HiddenFor(model => model.Album.AlbumId )

        <div class="editor-label">

            @Html.LabelFor(model => model.Album.GenreId, "Genre")

        </div>

        <div class="editor-field">

            @Html.DropDownList("Album.GenreId", Model.Genres)

            @Html.ValidationMessageFor(model => model.Album.GenreId)

        </div>

        <div class="editor-label">

            @Html.LabelFor(model => model.Album.ArtistId, "Artist")

        </div>

        <div class="editor-field">

            @Html.DropDownList("Album.ArtistId", Model.Artists)

            @Html.ValidationMessageFor(model => model.Album.ArtistId)

        </div>

        <div class="editor-label">

            @Html.LabelFor(model => model.Album.Title)

        </div>

        <div class="editor-field">

            @Html.EditorFor(model => model.Album.Title)

            @Html.ValidationMessageFor(model => model.Album.Title)

        </div>

        <div class="editor-label">

            @Html.LabelFor(model => model.Album.Price)

        </div>

        <div class="editor-field">

            @Html.EditorFor(model => model.Album.Price)

            @Html.ValidationMessageFor(model => model.Album.Price)

        </div>

        <div class="editor-label">

            @Html.LabelFor(model => model.Album.AlbumArtUrl)

        </div>

        <div class="editor-field">

            @Html.EditorFor(model => model.Album.AlbumArtUrl)

            @Html.ValidationMessageFor(model => model.Album.AlbumArtUrl)

        </div>

        <p>

            <input type="submit" value="Save" />

        </p>

    </fieldset>

}

<div>

    @Html.ActionLink("Back to List", "Index")

</div>

태그는 EditVM 다음과 같은 예외가 있는 원래 Edit 태그와 매우 유사합니다.

  • 뷰의 Edit 모델 속성은 형식 model.property입니다(예: model.Title ). 뷰의 EditVm 모델 속성은 형식 model.Album.property입니다(예: model.Album.Title). 뷰가 뷰의 EditVM 와 같이 가 아닌 에 Album대한 컨테이너를 Album 전달하기 때문 Edit 입니다.
  • DropDownList 두 번째 매개 변수는 ViewBag이 아닌 뷰 모델에서 가져옵니다.
  • 보기의 BeginForm 도우미는 EditVM 작업 메서드에 Edit 명시적으로 다시 게시합니다. 작업에 다시 게시하면 Edit 작업을 작성 HTTP POST EditVM 할 필요가 없으며 작업을 다시 사용할 HTTP POSTEdit 수 있습니다.

애플리케이션을 실행하고 앨범을 편집합니다. 를 사용하도록 EditVMURL을 변경합니다. 필드를 변경하고 저장 단추를 눌러 코드가 작동하는지 확인합니다.

U RL이 V M 편집으로 변경된 이미지

어떤 방법을 사용해야 하나요?

표시된 세 가지 접근 방식은 모두 허용됩니다. 많은 개발자는 를 사용하여 를 에 명시적으로 전달하는 SelectListDropDownList 것을 선호합니다 ViewBag. 이 방법은 컬렉션에 보다 적절한 이름을 사용할 수 있는 유연성을 제공하는 추가적인 이점이 있습니다. 한 가지 주의할 점은 개체의 ViewBag SelectList 이름을 model 속성과 같은 이름으로 지정할 수 없다는 것입니다.

일부 개발자는 ViewModel 접근 방식을 선호합니다. 다른 사람들은 ViewModel 접근 방식의 더 자세한 태그 및 생성된 HTML을 단점으로 간주합니다.

이 섹션에서는 범주 데이터와 함께 DropDownList 를 사용하는 세 가지 방법을 알아보았습니다. 다음 섹션에서는 새 범주를 추가하는 방법을 보여 드리겠습니다.