Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
oleh Rick Anderson
Di Penjelajah Solusi, klik kanan folder Pengontrol lalu pilih Tambahkan Pengontrol. Beri nama pengontrol StoreManagerController. Atur opsi untuk dialog Tambahkan Pengontrol seperti yang ditunjukkan pada gambar di bawah ini.

Edit tampilan StoreManager\Index.cshtml dan hapus AlbumArtUrl. Menghapus AlbumArtUrl akan membuat presentasi lebih mudah dibaca. Kode yang telah selesai ditunjukkan di bawah ini.
@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>
Buka file Controllers\StoreManagerController.cs dan temukan metode .Index OrderBy Tambahkan klausa sehingga album akan diurutkan berdasarkan harga. Kode lengkap ditunjukkan di bawah ini.
public ViewResult Index()
{
var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist)
.OrderBy(a => a.Price);
return View(albums.ToList());
}
Mengurutkan berdasarkan harga akan memudahkan pengujian perubahan pada database. Saat menguji metode edit dan buat, Anda dapat menggunakan harga rendah sehingga data yang disimpan akan muncul terlebih dahulu.
Buka file StoreManager\Edit.cshtml. Tambahkan baris berikut tepat setelah tag legenda.
@Html.HiddenFor(model => model.AlbumId)
Kode berikut menunjukkan konteks perubahan ini:
@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 diperlukan untuk membuat perubahan pada rekaman album.
Klik CTRL + F5 untuk menjalankan aplikasi. Pilih tautan Admin , lalu pilih tautan Buat Baru untuk membuat album baru. Verifikasi bahwa informasi album telah disimpan. Edit album dan verifikasi perubahan yang Anda buat dipertahankan.
Skema Album
StoreManager Pengontrol yang dibuat oleh mekanisme perancah MVC memungkinkan akses CRUD (Buat, Baca, Perbarui, Hapus) ke album di database penyimpanan musik. Skema untuk informasi album ditunjukkan di bawah ini:

Tabel Albums tidak menyimpan genre dan deskripsi album, tabel menyimpan kunci asing ke Genres tabel. Tabel Genres berisi nama dan deskripsi genre. Demikian juga, Albums tabel tidak berisi nama artis album, tetapi kunci asing untuk Artists tabel. Tabel Artists berisi nama artis. Jika Anda memeriksa data dalam Albums tabel, Anda dapat melihat setiap baris berisi kunci asing ke Genres tabel dan kunci asing ke Artists tabel. Gambar di bawah ini memperlihatkan beberapa data tabel dari Albums tabel.

Tag Pilih HTML
Elemen HTML <select> (dibuat oleh pembantu DropDownList HTML) digunakan untuk menampilkan daftar lengkap nilai (seperti daftar genre). Untuk formulir edit, saat nilai saat ini diketahui, daftar pilih dapat menampilkan nilai saat ini. Kami melihat ini sebelumnya ketika kami menetapkan nilai yang dipilih ke Comedy. Daftar pemilihan sangat ideal untuk menampilkan kategori atau data kunci asing. Elemen <select> untuk kunci asing Genre menampilkan daftar kemungkinan nama genre, tetapi ketika Anda menyimpan formulir, properti Genre diperbarui dengan nilai kunci asing Genre, bukan nama genre yang ditampilkan. Pada gambar di bawah ini, genre yang dipilih adalah Disco dan artisnya adalah Donna Summer.

Memeriksa Kode Perancah MVC ASP.NET
Buka file Controllers\StoreManagerController.cs dan temukan metode .HTTP GET Create
public ActionResult Create()
{
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name");
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");
return View();
}
Metode ini Create menambahkan dua objek SelectList ke ViewBag, satu untuk berisi informasi genre, dan satu untuk berisi informasi artis. Overload konstruktor SelectList yang digunakan di atas mengambil tiga argumen:
public SelectList(
IEnumerable items,
string dataValueField,
string dataTextField
)
- item: IEnumerable yang berisi item dalam daftar. Dalam contoh di atas, daftar genre yang dikembalikan oleh
db.Genres. - dataValueField: Nama properti dalam daftar IEnumerable yang berisi nilai kunci. Dalam contoh di atas,
GenreIddanArtistId. - dataTextField: Nama properti dalam daftar IEnumerable yang berisi informasi yang akan ditampilkan. Dalam artis dan tabel genre,
namebidang digunakan.
Buka file Views\StoreManager\Create.cshtml dan periksa markup pembantu Html.DropDownList untuk bidang genre.
@model MvcMusicStore.Models.Album
@* Markup removed for clarity.*@
@Html.DropDownList("GenreId", String.Empty)
Baris pertama menunjukkan bahwa tampilan buat mengambil Album model. Dalam metode yang ditunjukkan Create di atas, tidak ada model yang diteruskan, sehingga tampilan mendapatkan model nullAlbum. Pada titik ini kami membuat album baru sehingga kami tidak memiliki data untuk Album itu.
Overload Html.DropDownList yang ditunjukkan di atas mengambil nama bidang untuk mengikat model. Ini juga menggunakan nama ini untuk mencari objek ViewBag yang berisi objek SelectList . Dengan menggunakan kelebihan beban ini, Anda diharuskan untuk memberi nama objek GenreIdViewBag SelectList . Parameter kedua (String.Empty) adalah teks yang ditampilkan ketika tidak ada item yang dipilih. Inilah yang kita inginkan saat membuat album baru. Jika Anda menghapus parameter kedua dan menggunakan kode berikut:
@Html.DropDownList("GenreId")
Daftar pilihan akan default ke elemen pertama, atau Rock dalam sampel kami.

Memeriksa metode .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);
}
Kelebihan metode Create ini mengambil album objek, yang dibuat oleh sistem pengikatan model MVC ASP.NET dari nilai formulir yang diposting. Saat Anda mengirimkan album baru, jika status model valid dan tidak ada kesalahan database, album baru ditambahkan database. Gambar berikut menunjukkan pembuatan album baru.

Anda dapat menggunakan alat fiddler untuk memeriksa nilai formulir yang diposting yang ASP.NET penggunaan pengikatan model MVC untuk membuat objek album.
.
Merefaktor Pembuatan Daftar Pilih ViewBag
Edit Metode dan HTTP POST Create metode memiliki kode yang identik untuk menyiapkan SelectList di ViewBag. Dalam semangat DRY, kita akan merefaktor kode ini. Kita akan menggunakan kode yang direfaktor ini nanti.
Buat metode baru untuk menambahkan genre dan artis SelectList ke ViewBag.
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);
}
Ganti dua baris yang mengatur ViewBag di masing-masing Create metode dan Edit dengan panggilan ke SetGenreArtistViewBag metode . Kode yang telah selesai ditunjukkan di bawah ini.
//
// 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);
}
Buat album baru dan edit album untuk memverifikasi perubahan yang berfungsi.
Secara Eksplisit Meneruskan SelectList ke DropDownList
Tampilan buat dan edit yang dibuat oleh perancah MVC ASP.NET menggunakan overload DropDownList berikut:
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 Markup untuk tampilan buat ditunjukkan di bawah ini.
@Html.DropDownList("GenreId", String.Empty)
ViewBag Karena properti untuk SelectList diberi nama GenreId, pembantu DropDownList akan menggunakan GenreIdSelectList di ViewBag. Dalam overload DropDownList berikut, SelectList secara eksplisit diteruskan.
public static MvcHtmlString DropDownList(
this HtmlHelper htmlHelper,
string name, // The name of the ViewModel property to bind.
IEnumerable selectList // The SelectList
)
Buka file Views\StoreManager\Edit.cshtml, dan ubah panggilan DropDownList untuk secara eksplisit meneruskan SelectList, menggunakan kelebihan beban di atas. Lakukan ini untuk kategori Genre. Kode yang telah selesai ditunjukkan di bawah ini:
@Html.DropDownList("GenreId", ViewBag.GenreId as SelectList)
Jalankan aplikasi dan klik tautan Admin , lalu navigasikan ke album Jazz dan pilih tautan Edit .

Alih-alih menampilkan Jazz sebagai genre yang saat ini dipilih, Rock ditampilkan. Ketika argumen string (properti untuk mengikat) dan objek SelectList memiliki nama yang sama, nilai yang dipilih tidak digunakan. Ketika tidak ada nilai yang dipilih yang disediakan, browser default ke elemen pertama dalam SelectList(yang merupakan Rock dalam contoh di atas). Ini adalah batasan yang diketahui dari pembantu DropDownList .
Buka file Controllers\StoreManagerController.cs dan ubah nama objek SelectList menjadi Genres dan Artists. Kode yang telah selesai ditunjukkan di bawah ini:
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);
}
Nama Genre dan Artis adalah nama yang lebih baik untuk kategori, karena berisi lebih dari sekadar ID dari setiap kategori. Pemfaktoran ulang yang kami lakukan sebelumnya terbayar. Alih-alih mengubah ViewBag dalam empat metode, perubahan kami diisolasi ke SetGenreArtistViewBag metode .
Ubah panggilan DropDownList di tampilan buat dan edit untuk menggunakan nama SelectList baru. Markup baru untuk tampilan edit ditunjukkan di bawah ini:
<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>
Tampilan Buat memerlukan string kosong untuk mencegah item pertama dalam SelectList ditampilkan.
<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>
Buat album baru dan edit album untuk memverifikasi perubahan yang berfungsi. Uji kode edit dengan memilih album dengan genre selain Rock.
Menggunakan Model Tampilan dengan Pembantu DropDownList
Buat kelas baru di folder ViewModels bernama AlbumSelectListViewModel. Ganti kode di AlbumSelectListViewModel kelas dengan yang berikut:
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);
}
}
}
Konstruktor AlbumSelectListViewModel mengambil album, daftar artis dan genre dan membuat objek yang berisi album dan SelectList untuk genre dan artis.
Bangun proyek sehingga AlbumSelectListViewModel tersedia saat kita membuat tampilan di langkah berikutnya.
EditVM Tambahkan metode ke StoreManagerController. Kode yang telah selesai ditunjukkan di bawah ini.
//
// 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);
}
AlbumSelectListViewModelKlik kanan , pilih Atasi, lalu gunakan MvcMusicStore.ViewModels;.

Atau, Anda dapat menambahkan pernyataan penggunaan berikut:
using MvcMusicStore.ViewModels;
EditVM Klik kanan dan pilih Tambahkan Tampilan. Gunakan opsi yang ditunjukkan di bawah ini.

Pilih Tambahkan, lalu ganti konten file Views\StoreManager\EditVM.cshtml dengan yang berikut ini:
@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 Markup sangat mirip dengan markup asli Edit dengan pengecualian berikut.
- Properti model
Editdalam tampilan adalah formulirmodel.property(misalnya,model.Title). Properti modelEditVmdalam tampilan adalah formulirmodel.Album.property(misalnya,model.Album.Title). Itu karenaEditVMtampilan diteruskan kontainer untukAlbum, bukanAlbumsebagai dalamEdittampilan. - Parameter kedua DropDownList berasal dari model tampilan, bukan ViewBag.
- Pembantu BeginForm dalam
EditVMtampilan secara eksplisit memposting kembali keEditmetode tindakan. Dengan memposting kembali keEdittindakan, kita tidak perlu menulisHTTP POST EditVMtindakan dan dapat menggunakan kembali tindakan.HTTP POSTEdit
Jalankan aplikasi dan edit album. Ubah URL untuk menggunakan EditVM. Ubah bidang dan tekan tombol Simpan untuk memverifikasi kode berfungsi.

Pendekatan mana yang harus Anda gunakan?
Ketiga pendekatan yang ditampilkan dapat diterima. Banyak pengembang lebih suka secara eksplisit meneruskan SelectList ke DropDownList menggunakan ViewBag. Pendekatan ini memiliki keuntungan tambahan untuk memberi Anda fleksibilitas menggunakan nama yang lebih sesuai untuk koleksi. Satu peringatan adalah Anda tidak dapat memberi nama ViewBag SelectList objek dengan nama yang sama dengan properti model.
Beberapa pengembang lebih suka pendekatan ViewModel. Yang lain menganggap markup yang lebih verbose dan HTML yang dihasilkan dari pendekatan ViewModel merugikan.
Di bagian ini kita telah mempelajari tiga pendekatan untuk menggunakan DropDownList dengan data kategori. Di bagian berikutnya, kita akan menunjukkan cara menambahkan kategori baru.