ASP.NET MVC tarafından DropDownList yardımcısı için nasıl iskele oluşturulduğunu inceleme
tarafından Rick Anderson
Çözüm Gezgini'da Denetleyiciler klasörüne sağ tıklayın ve ardından Denetleyici Ekle'yi seçin. Denetleyiciye StoreManagerController adını verin. Aşağıdaki resimde gösterildiği gibi Denetleyici Ekle iletişim kutusunun seçeneklerini ayarlayın.
StoreManager\Index.cshtml görünümünü düzenleyin ve kaldırınAlbumArtUrl
. Kaldırma işlemi AlbumArtUrl
sunuyu daha okunabilir hale getirir. Tamamlanmış kod aşağıda gösterilmiştir.
@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 dosyasını açın ve yöntemini bulunIndex
. Albümlerin OrderBy
fiyata göre sıralanması için yan tümcesini ekleyin. Kodun tamamı aşağıda gösterilmiştir.
public ViewResult Index()
{
var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist)
.OrderBy(a => a.Price);
return View(albums.ToList());
}
Fiyata göre sıralamak, veritabanındaki değişiklikleri test etme işlemini kolaylaştırır. Düzenleme ve oluşturma yöntemlerini test ederken, kaydedilen verilerin önce görünmesi için düşük bir fiyat kullanabilirsiniz.
StoreManager\Edit.cshtml dosyasını açın. Gösterge etiketinin hemen arkasına aşağıdaki satırı ekleyin.
@Html.HiddenFor(model => model.AlbumId)
Aşağıdaki kod bu değişikliğin bağlamını gösterir:
@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
bir albüm kaydında değişiklik yapmak için gereklidir.
Uygulamayı çalıştırmak için CTRL+F5'e basın. Yönetici bağlantısına gidin ve ardından Yeni Oluştur bağlantısını seçerek yeni bir albüm oluşturun. Albüm bilgilerinin kaydedildiği doğrulayın. Bir albümü düzenleyin ve yaptığınız değişikliklerin kalıcı olduğunu doğrulayın.
Albüm Şeması
StoreManager
MVC iskele mekanizması tarafından oluşturulan denetleyici, CRUD'nin (Oluşturma, Okuma, Güncelleştirme, Silme) müzik deposu veritabanındaki albümlere erişmesine izin verir. Albüm bilgileri şeması aşağıda gösterilmiştir:
Tablo albüm Albums
türünü ve açıklamasını depolamaz, tablonun yabancı anahtarını Genres
depolar. Genres
Tabloda tür adı ve açıklaması yer alır. Benzer şekilde, Albums
tabloda albüm sanatçılarının adı değil, tablonun yabancı anahtarı Artists
yer alır. Tabloda Artists
sanatçının adı yer alır. Tablodaki verileri incelerseniz, her satırın Albums
tablo için Genres
bir yabancı anahtar ve tabloya yabancı anahtar içerdiğini Artists
görebilirsiniz. Aşağıdaki resimde tablodan bazı tablo verileri gösterilmektedir Albums
.
HTML Select Etiketi
HTML <select>
öğesi (HTML DropDownList yardımcısı tarafından oluşturulan), değerlerin tam listesini (tür listesi gibi) görüntülemek için kullanılır. Düzenleme formları için, geçerli değer bilindiğinde, seçme listesi geçerli değeri görüntüleyebilir. Bunu daha önce, seçilen değeri Comedy olarak ayarladığımızda görmüştük. Seçme listesi, kategori veya yabancı anahtar verilerini görüntülemek için idealdir. <select>
Genre yabancı anahtarının öğesi olası tür adlarının listesini görüntüler, ancak formu kaydettiğinizde Tarz özelliği görüntülenen tür adıyla değil, Tarz yabancı anahtar değeriyle güncelleştirilir. Aşağıdaki resimde, seçilen tarz Disco, sanatçı ise Donna Summer' dır.
ASP.NET MVC yapı iskelesi kodunu inceleme
Controllers\StoreManagerController.cs dosyasını açın ve yöntemini bulunHTTP GET Create
.
public ActionResult Create()
{
ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name");
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name");
return View();
}
yöntemi, Create
biri tarz bilgilerini, biri de sanatçı bilgilerini içerecek şekilde öğesine iki SelectList nesnesi ViewBag
ekler. Yukarıda kullanılan SelectList oluşturucu aşırı yüklemesi üç bağımsız değişken alır:
public SelectList(
IEnumerable items,
string dataValueField,
string dataTextField
)
- items: Listedeki öğeleri içeren bir IEnumerable . Yukarıdaki örnekte, tarafından
db.Genres
döndürülen türlerin listesi. - dataValueField: Anahtar değerini içeren IEnumerable listesindeki özelliğin adı. Yukarıdaki
GenreId
örnekte veArtistId
. - dataTextField: Görüntülenecek bilgileri içeren IEnumerable listesindeki özelliğin adı. Hem sanatçılar hem de tarz tablosunda
name
alan kullanılır.
Views\StoreManager\Create.cshtml dosyasını açın ve tür alanının yardımcı işaretlemesini inceleyinHtml.DropDownList
.
@model MvcMusicStore.Models.Album
@* Markup removed for clarity.*@
@Html.DropDownList("GenreId", String.Empty)
İlk satır, oluşturma görünümünün bir Album
model aldığını gösterir. Yukarıda gösterilen yöntemde Create
hiçbir model geçirilmiyor, bu nedenle görünüm null Album
model alıyor. Bu noktada yeni bir albüm oluşturuyoruz, bu nedenle bu albümle ilgili hiçbir Album
verimiz yok.
Yukarıda gösterilen Html.DropDownList aşırı yüklemesi, modele bağlanacak alanın adını alır. SelectList nesnesi içeren bir ViewBag nesnesini aramak için de bu adı kullanır. Bu aşırı yüklemeyi kullanarak, ViewBag SelectList nesnesini GenreId
adlandırmanız gerekir. İkinci parametre (String.Empty
), hiçbir öğe seçilmediğinde görüntülenecek metindir. Yeni bir albüm oluştururken tam olarak bunu istiyoruz. İkinci parametreyi kaldırdıysanız ve aşağıdaki kodu kullandıysanız:
@Html.DropDownList("GenreId")
Seçme listesi varsayılan olarak ilk öğeyi veya örneğimizdeki Rock öğesini kullanır.
yöntemi inceleniyor 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);
}
Yönteminin Create
bu aşırı yüklemesi, ASP.NET MVC model bağlama sistemi tarafından gönderilen form değerlerinden oluşturulan bir album
nesnesi alır. Yeni bir albüm gönderdiğinizde, model durumu geçerliyse ve veritabanı hatası yoksa, yeni albüm veritabanına eklenir. Aşağıdaki görüntüde yeni bir albümün oluşturulması gösterilmektedir.
MVC model bağlamasının albüm nesnesini oluşturmak için kullandığı ASP.NET gönderilen form değerlerini incelemek için fiddler aracını kullanabilirsiniz.
.
ViewBag SelectList Oluşturmayı Yeniden Düzenleme
Edit
Hem yöntemler hem HTTP POST Create
de yöntem, ViewBag'te SelectList'i ayarlamak için aynı koda sahiptir. DRY ruhuyla bu kodu yeniden düzenleyeceğiz. Bu yeniden düzenlenmiş kodu daha sonra kullanacağız.
ViewBag'e bir tür ve sanatçı SelectList eklemek için yeni bir yöntem oluşturun.
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);
}
ve Edit
yöntemlerinin her birinde Create
öğesini ayarlayıp ViewBag
yöntemini çağıran SetGenreArtistViewBag
iki satırı değiştirin. Tamamlanmış kod aşağıda gösterilmiştir.
//
// 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);
}
Değişikliklerin çalıştığını doğrulamak için yeni bir albüm oluşturun ve bir albümü düzenleyin.
SelectList'i DropDownList'e Açıkça Geçirme
ASP.NET MVC iskelesi tarafından oluşturulan oluşturma ve düzenleme görünümleri aşağıdaki DropDownList aşırı yüklemesini kullanır:
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"
)
Oluşturma DropDownList
görünümü için işaretleme aşağıda gösterilmiştir.
@Html.DropDownList("GenreId", String.Empty)
ViewBag
için SelectList
özelliği adlı GenreId
olduğundan DropDownList yardımcısı ViewBag'teki SelectList değerini kullanırGenreId
. Aşağıdaki DropDownList aşırı yüklemesinde açıkça SelectList
geçirilir.
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 dosyasını açın ve yukarıdaki aşırı yüklemeyi kullanarak DropDownList çağrısını SelectList'e açıkça geçecek şekilde değiştirin. Bunu Tarz kategorisi için yapın. Tamamlanmış kod aşağıda gösterilmiştir:
@Html.DropDownList("GenreId", ViewBag.GenreId as SelectList)
Uygulamayı çalıştırın ve Yönetici bağlantısına tıklayın, ardından bir Jazz albümüne gidin ve Düzenle bağlantısını seçin.
Şu anda seçili olan tür olarak Jazz'ı göstermek yerine Rock görüntülenir. Dize bağımsız değişkeni (bağlanacak özellik) ve SelectList nesnesi aynı ada sahip olduğunda, seçili değer kullanılmaz. Sağlanan seçili değer olmadığında, tarayıcılar varsayılan olarak SelectList'teki ilk öğeye (yukarıdaki örnekte Rock değeridir) ayarlanır. Bu, DropDownList yardımcısının bilinen bir sınırlamasıdır.
Controllers\StoreManagerController.cs dosyasını açın ve SelectList nesne adlarını ve Artists
olarak Genres
değiştirin. Tamamlanmış kod aşağıda gösterilmiştir:
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);
}
Türler ve Sanatçılar adları, her kategorinin kimliğinden daha fazlasını içerdiğinden kategoriler için daha iyi adlardır. Daha önce yaptığımız yeniden düzenlemenin bedeli ödendi. ViewBag'i dört yöntemde değiştirmek yerine, değişikliklerimiz yöntemine SetGenreArtistViewBag
yalıtıldı.
Yeni SelectList adlarını kullanmak için oluşturma ve düzenleme görünümlerindeki DropDownList çağrısını değiştirin. Düzenleme görünümü için yeni işaretleme aşağıda gösterilmiştir:
<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>
Oluştur görünümü, SelectList içindeki ilk öğenin görüntülenmesini önlemek için boş bir dize gerektirir.
<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>
Değişikliklerin çalıştığını doğrulamak için yeni bir albüm oluşturun ve bir albümü düzenleyin. Rock dışında bir tarza sahip bir albüm seçerek düzenleme kodunu test edin.
DropDownList Yardımcısı ile Görünüm Modeli Kullanma
ViewModels klasöründe adlı AlbumSelectListViewModel
yeni bir sınıf oluşturun. sınıfındaki AlbumSelectListViewModel
kodu aşağıdakilerle değiştirin:
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);
}
}
}
Oluşturucu AlbumSelectListViewModel
bir albüm, sanatçıların ve tarzların bir listesini alır ve albümü içeren bir nesne ve tarzlar ve sanatçılar için bir SelectList
nesne oluşturur.
Sonraki adımda bir görünüm oluşturduğunuzda kullanılabilir olacak şekilde AlbumSelectListViewModel
projeyi oluşturun.
öğesine StoreManagerController
bir EditVM
yöntem ekleyin. Tamamlanmış kod aşağıda gösterilmiştir.
//
// 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);
}
sağ tıklayınAlbumSelectListViewModel
, Çözümle'yi seçin, ardından MvcMusicStore.ViewModels; komutunu kullanarak.
Alternatif olarak, aşağıdaki using deyimini de ekleyebilirsiniz:
using MvcMusicStore.ViewModels;
Sağ tıklayın EditVM
ve Görünüm Ekle'yi seçin. Aşağıda gösterilen seçenekleri kullanın.
Ekle'yi seçin, ardından Views\StoreManager\EditVM.cshtml dosyasının içeriğini aşağıdakilerle değiştirin:
@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>
İşaretlemeyi EditVM
aşağıdaki özel durumlarla özgün Edit
işaretlemeye çok benzer.
- Görünümdeki
Edit
model özellikleri formdadırmodel.property
(örneğin,model.Title
). GörünümdekiEditVm
model özellikleri formdadırmodel.Album.property
(örneğin,model.Album.Title
). Bunun nedeni, görünümün görünümdeEditVM
olduğu gibi değil için birAlbum
Album
kapsayıcıya geçirilmesidirEdit
. - DropDownList ikinci parametresi ViewBag'ten değil görünüm modelinden gelir.
- Görünümdeki
EditVM
BeginForm yardımcısı açıkça eylem yöntemineEdit
geri gönderir. EylemeEdit
geri göndererek birHTTP POST EditVM
eylem yazmamız gerekmez ve eylemi yenidenHTTP POST
Edit
kullanabiliriz.
Uygulamayı çalıştırın ve bir albümü düzenleyin. URL'yi kullanacak EditVM
şekilde değiştirin. Bir alanı değiştirin ve kodun çalıştığını doğrulamak için Kaydet düğmesine basın.
Hangi Yaklaşımı Kullanmalısınız?
Gösterilen üç yaklaşım da kabul edilebilir. Birçok geliştirici açıkça kullanarak ViewBag
'ı 'a geçirmeyi SelectList
DropDownList
tercih eder. Bu yaklaşım, koleksiyon için daha uygun bir ad kullanma esnekliği vermenin ek avantajına sahiptir. Tek uyarı, nesneye ViewBag SelectList
model özelliğiyle aynı adı veremeyeceğinizdir.
Bazı geliştiriciler ViewModel yaklaşımını tercih eder. Diğerleri ViewModel yaklaşımının daha ayrıntılı işaretlemesini ve oluşturulan HTML'sini dezavantaj olarak kabul eder.
Bu bölümde DropDownList'i kategori verileriyle kullanma konusunda üç yaklaşım öğrendik. Sonraki bölümde yeni kategori eklemeyi göstereceğiz.