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 Microsoft
Ini adalah langkah 5 dari tutorial aplikasi "NerdDinner" gratis yang memandu cara membangun aplikasi web kecil, tetapi lengkap menggunakan ASP.NET MVC 1.
Langkah 5 menunjukkan cara mengikuti kelas DinnersController kami lebih jauh dengan mengaktifkan dukungan untuk mengedit, membuat, dan menghapus Makan Malam dengannya juga.
Jika Anda menggunakan ASP.NET MVC 3, kami sarankan Anda mengikuti tutorial Memulai MVC 3 atau MVC Music Store .
NerdDinner Langkah 5: Buat, Perbarui, Hapus Skenario Formulir
Kami telah memperkenalkan pengontrol dan tampilan, dan membahas cara menggunakannya untuk mengimplementasikan pengalaman daftar/detail untuk Makan Malam di lokasi. Langkah kami selanjutnya adalah mengambil kelas DinnersController kami lebih lanjut dan memungkinkan dukungan untuk mengedit, membuat, dan menghapus Makan Malam dengannya juga.
URL yang ditangani oleh DinnersController
Kami sebelumnya menambahkan metode tindakan ke DinnersController yang menerapkan dukungan untuk dua URL: /Dinners and /Dinners/Details/[id].
| URL | VERBA | Tujuan |
|---|---|---|
| /Makan malam/ | GET | Tampilkan daftar HTML makan malam mendatang. |
| /Dinners/Details/[id] | GET | Tampilkan detail tentang makan malam tertentu. |
Kami sekarang akan menambahkan metode tindakan untuk mengimplementasikan tiga URL tambahan: /Dinners/Edit/[id], /Dinners/Create, dan /Dinners/Delete/[id]. URL ini akan memungkinkan dukungan untuk mengedit Makan Malam yang ada, membuat Makan Malam baru, dan menghapus Makan Malam.
Kami akan mendukung interaksi kata kerja HTTP GET dan HTTP POST dengan URL baru ini. Permintaan HTTP GET ke URL ini akan menampilkan tampilan HTML awal data (formulir yang diisi dengan data Makan Malam dalam kasus "edit", formulir kosong dalam kasus "buat", dan layar konfirmasi penghapusan dalam kasus "hapus"). Permintaan HTTP POST ke URL ini akan menyimpan/memperbarui/menghapus data Makan Malam di DinnerRepository kami (dan dari sana ke database).
| URL | VERBA | Tujuan |
|---|---|---|
| /Dinners/Edit/[id] | GET | Menampilkan formulir HTML yang dapat diedit yang diisi dengan data Makan Malam. |
| POST | Simpan perubahan formulir untuk Makan Malam tertentu ke database. | |
| /Dinners/Create | GET | Tampilkan formulir HTML kosong yang memungkinkan pengguna menentukan Makan Malam baru. |
| POST | Buat Makan Malam baru dan simpan di database. | |
| /Dinners/Delete/[id] | GET | Tampilkan layar konfirmasi penghapusan. |
| POST | Menghapus makan malam yang ditentukan dari database. |
Edit Dukungan
Mari kita mulai dengan menerapkan skenario "edit".
Metode Tindakan Edit HTTP-GET
Kita akan mulai dengan menerapkan perilaku HTTP "GET" dari metode tindakan edit kita. Metode ini akan dipanggil ketika URL /Dinners/Edit/[id] diminta. Implementasi kami akan terlihat seperti:
//
// GET: /Dinners/Edit/2
public ActionResult Edit(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
return View(dinner);
}
Kode di atas menggunakan DinnerRepository untuk mengambil objek Makan Malam. Kemudian merender templat Tampilan menggunakan objek Makan Malam. Karena kami belum secara eksplisit meneruskan nama templat ke metode pembantu View(), itu akan menggunakan jalur default berbasis konvensi untuk menyelesaikan templat tampilan: /Views/Dinners/Edit.aspx.
Sekarang mari kita buat templat tampilan ini. Kami akan melakukan ini dengan mengklik kanan dalam metode Edit dan memilih perintah menu konteks "Tambahkan Tampilan":
Dalam dialog "Tambahkan Tampilan" kami akan menunjukkan bahwa kami meneruskan objek Makan Malam ke templat tampilan kami sebagai modelnya, dan memilih untuk merancang templat "Edit" secara otomatis:
Ketika kami mengklik tombol "Tambahkan", Visual Studio akan menambahkan file templat tampilan "Edit.aspx" baru untuk kami dalam direktori "\Views\Dinners". Ini juga akan membuka templat tampilan "Edit.aspx" baru dalam editor kode - diisi dengan implementasi perancah "Edit" awal seperti di bawah ini:
Mari kita buat beberapa perubahan pada perancah "edit" default yang dihasilkan, dan perbarui templat tampilan edit agar memiliki konten di bawah ini (yang menghapus beberapa properti yang tidak ingin kami ekspos):
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
Edit: <%=Html.Encode(Model.Title)%>
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
<h2>Edit Dinner</h2>
<%=Html.ValidationSummary("Please correct the errors and try again.") %>
<% using (Html.BeginForm()) { %>
<fieldset>
<p>
<label for="Title">Dinner Title:</label>
<%=Html.TextBox("Title") %>
<%=Html.ValidationMessage("Title", "*") %>
</p>
<p>
<label for="EventDate">EventDate:</label>
<%=Html.TextBox("EventDate", String.Format("{0:g}", Model.EventDate))%>
<%=Html.ValidationMessage("EventDate", "*") %>
</p>
<p>
<label for="Description">Description:</label>
<%=Html.TextArea("Description") %>
<%=Html.ValidationMessage("Description", "*")%>
</p>
<p>
<label for="Address">Address:</label>
<%=Html.TextBox("Address") %>
<%=Html.ValidationMessage("Address", "*") %>
</p>
<p>
<label for="Country">Country:</label>
<%=Html.TextBox("Country") %>
<%=Html.ValidationMessage("Country", "*") %>
</p>
<p>
<label for="ContactPhone">ContactPhone #:</label>
<%=Html.TextBox("ContactPhone") %>
<%=Html.ValidationMessage("ContactPhone", "*") %>
</p>
<p>
<label for="Latitude">Latitude:</label>
<%=Html.TextBox("Latitude") %>
<%=Html.ValidationMessage("Latitude", "*") %>
</p>
<p>
<label for="Longitude">Longitude:</label>
<%=Html.TextBox("Longitude") %>
<%=Html.ValidationMessage("Longitude", "*") %>
</p>
<p>
<input type="submit" value="Save"/>
</p>
</fieldset>
<% } %>
</asp:Content>
Ketika kita menjalankan aplikasi dan meminta URL "/Dinners/Edit/1" kita akan melihat halaman berikut:
Markup HTML yang dihasilkan oleh tampilan kami terlihat seperti di bawah ini. Ini adalah HTML standar - dengan <elemen formulir> yang melakukan HTTP POST ke URL /Dinners/Edit/1 ketika tombol "Simpan" <input type="submit"/> didorong. Elemen html <input type="text"/> telah menjadi output untuk setiap properti yang dapat diedit:
Metode Pembantu Html.BeginForm() dan Html.TextBox() Html
Templat tampilan "Edit.aspx" kami menggunakan beberapa metode "Html Helper": Html.ValidationSummary(), Html.BeginForm(), Html.TextBox(), dan Html.ValidationMessage(). Selain menghasilkan markup HTML untuk kami, metode pembantu ini menyediakan penanganan kesalahan bawaan dan dukungan validasi.
Metode pembantu Html.BeginForm()
Metode pembantu Html.BeginForm() adalah output elemen formulir> HTML <dalam markup kami. Dalam templat tampilan Edit.aspx kami, Anda akan melihat bahwa kami menerapkan pernyataan "menggunakan" C# saat menggunakan metode ini. Kurung kurawal terbuka menunjukkan awal <konten formulir> , dan kurung kurawal penutup adalah apa yang menunjukkan akhir <elemen /form> :
<% using (Html.BeginForm()) { %>
<fieldset>
<!-- Fields Omitted for Brevity -->
<p>
<input type="submit" value="Save"/>
</p>
</fieldset>
<% } %>
Atau, jika Anda menemukan pendekatan pernyataan "menggunakan" tidak wajar untuk skenario seperti ini, Anda dapat menggunakan kombinasi Html.BeginForm() dan Html.EndForm() (yang melakukan hal yang sama):
<% Html.BeginForm(); %>
<fieldset>
<!-- Fields Omitted for Brevity -->
<p>
<input type="submit" value="Save"/>
</p>
</fieldset>
<% Html.EndForm(); %>
Memanggil Html.BeginForm() tanpa parameter apa pun akan menyebabkannya menghasilkan elemen formulir yang melakukan HTTP-POST ke URL permintaan saat ini. Itulah sebabnya tampilan Edit kami menghasilkan <elemen form action="/Dinners/Edit/1" method="post"> . Kita bisa meneruskan parameter eksplisit secara alternatif ke Html.BeginForm() jika kita ingin memposting ke URL yang berbeda.
Metode pembantu Html.TextBox()
Tampilan Edit.aspx kami menggunakan metode pembantu Html.TextBox() untuk menghasilkan <elemen input type="text"/> :
<%= Html.TextBox("Title") %>
Metode Html.TextBox() di atas mengambil parameter tunggal – yang sedang digunakan untuk menentukan atribut id/name dari <elemen input type="text"/> ke output, serta properti model untuk mengisi nilai kotak teks. Misalnya, objek Makan Malam yang kami teruskan ke tampilan Edit memiliki nilai properti "Judul" ".NET Futures", dan jadi output panggilan metode Html.TextBox("Title") kami: <input id="Title" name="Title" type="text" value=".NET Futures" />.
Atau, kita dapat menggunakan parameter Html.TextBox() pertama untuk menentukan id/nama elemen, lalu secara eksplisit meneruskan nilai untuk digunakan sebagai parameter kedua:
<%= Html.TextBox("Title", Model.Title)%>
Seringkali kita ingin melakukan pemformatan kustom pada nilai yang merupakan output. Metode statis String.Format() bawaan .NET berguna untuk skenario ini. Templat tampilan Edit.aspx kami menggunakan ini untuk memformat nilai EventDate (yang berjenis DateTime) sehingga tidak menampilkan detik untuk waktu tersebut:
<%= Html.TextBox("EventDate", String.Format("{0:g}", Model.EventDate)) %>
Parameter ketiga untuk Html.TextBox() secara opsional dapat digunakan untuk menghasilkan atribut HTML tambahan. Cuplikan kode di bawah ini menunjukkan cara merender atribut size="30" tambahan dan atribut class="mycssclass" pada <elemen input type="text"/> . Perhatikan bagaimana kita melarikan diri dari nama atribut kelas menggunakan karakter "@" karena "kelas" adalah kata kunci yang dicadangkan di C#:
<%= Html.TextBox("Title", Model.Title, new { size=30, @class="myclass" } )%>
Menerapkan Metode Tindakan Edit HTTP-POST
Kami sekarang memiliki versi HTTP-GET dari metode tindakan Edit kami yang diterapkan. Ketika pengguna meminta URL /Dinners/Edit/1 , mereka menerima halaman HTML seperti berikut:
Menekan tombol "Simpan" menyebabkan posting formulir ke URL /Dinners/Edit/1, dan mengirimkan nilai formulir input> HTML <menggunakan kata kerja HTTP POST. Sekarang mari kita terapkan perilaku HTTP POST dari metode tindakan edit kami - yang akan menangani penyimpanan Makan Malam.
Kita akan mulai dengan menambahkan metode tindakan "Edit" yang kelebihan beban ke DinnersController kami yang memiliki atribut "AcceptVerbs" di dalamnya yang menunjukkan metode ini menangani skenario HTTP POST:
//
// POST: /Dinners/Edit/2
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues) {
...
}
Ketika atribut [AcceptVerbs] diterapkan ke metode tindakan yang kelebihan beban, ASP.NET MVC secara otomatis menangani permintaan pengiriman ke metode tindakan yang sesuai tergantung pada kata kerja HTTP masuk. PERMINTAAN HTTP POST ke URL /Dinners/Edit/[id] akan masuk ke metode Edit di atas, sementara semua permintaan kata kerja HTTP lainnya ke URL /Dinners/Edit/[id] akan masuk ke metode Edit pertama yang kami terapkan (yang tidak memiliki [AcceptVerbs] atribut).
| Topik Samping: Mengapa membedakan melalui kata kerja HTTP? |
|---|
| Anda mungkin bertanya - mengapa kita menggunakan satu URL dan membedakan perilakunya melalui kata kerja HTTP? Mengapa tidak hanya memiliki dua URL terpisah untuk menangani pemuatan dan penyimpanan perubahan edit? Misalnya: /Dinners/Edit/[id] untuk menampilkan formulir awal dan /Dinners/Save/[id] untuk menangani postingan formulir untuk menyimpannya? Kelemahan dengan menerbitkan dua URL terpisah adalah bahwa dalam kasus di mana kita memposting ke /Dinners/Save/2, dan kemudian perlu memutar ulang formulir HTML karena kesalahan input, pengguna akhir akan akhirnya memiliki URL /Dinners/Save/2 di bilah alamat browser mereka (karena itu adalah URL yang diposting formulir). Jika pengguna akhir menandai halaman yang diputar ulang ini ke daftar favorit browser mereka, atau menyalin/menempelkan URL dan mengirimnya melalui email ke teman, mereka akhirnya akan menyimpan URL yang tidak akan berfungsi di masa mendatang (karena URL tersebut bergantung pada nilai postingan). Dengan mengekspos satu URL (seperti: /Dinners/Edit/[id]) dan membedakannya dengan kata kerja HTTP, aman bagi pengguna akhir untuk menandai halaman edit dan/atau mengirim URL ke orang lain. |
Mengambil Nilai Posting formulir
Ada berbagai cara kami dapat mengakses parameter formulir yang diposting dalam metode "Edit" HTTP POST kami. Salah satu pendekatan sederhana adalah hanya menggunakan properti Permintaan pada kelas dasar Pengontrol untuk mengakses koleksi formulir dan mengambil nilai yang diposting secara langsung:
//
// POST: /Dinners/Edit/2
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues) {
// Retrieve existing dinner
Dinner dinner = dinnerRepository.GetDinner(id);
// Update dinner with form posted values
dinner.Title = Request.Form["Title"];
dinner.Description = Request.Form["Description"];
dinner.EventDate = DateTime.Parse(Request.Form["EventDate"]);
dinner.Address = Request.Form["Address"];
dinner.Country = Request.Form["Country"];
dinner.ContactPhone = Request.Form["ContactPhone"];
// Persist changes back to database
dinnerRepository.Save();
// Perform HTTP redirect to details page for the saved Dinner
return RedirectToAction("Details", new { id = dinner.DinnerID });
}
Pendekatan di atas sedikit verbose, terutama setelah kita menambahkan logika penanganan kesalahan.
Pendekatan yang lebih baik untuk skenario ini adalah memanfaatkan metode pembantu UpdateModel() bawaan pada kelas dasar Pengontrol. Ini mendukung pembaruan properti objek yang kita lewati menggunakan parameter formulir masuk. Ini menggunakan pantulan untuk menentukan nama properti pada objek, lalu secara otomatis mengonversi dan menetapkan nilai kepada mereka berdasarkan nilai input yang dikirimkan oleh klien.
Kita dapat menggunakan metode UpdateModel() untuk menyederhanakan Tindakan Edit HTTP-POST menggunakan kode ini:
//
// POST: /Dinners/Edit/2
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues) {
Dinner dinner = dinnerRepository.GetDinner(id);
UpdateModel(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id = dinner.DinnerID });
}
Kami sekarang dapat mengunjungi URL /Dinners/Edit/1 , dan mengubah judul Makan Malam kami:
Ketika kita mengklik tombol "Simpan", kita akan melakukan posting formulir ke tindakan Edit kita, dan nilai yang diperbarui akan bertahan dalam database. Kami kemudian akan diarahkan ke URL Detail untuk Makan Malam (yang akan menampilkan nilai yang baru disimpan):
Menangani Kesalahan Edit
Implementasi HTTP-POST kami saat ini berfungsi dengan baik - kecuali ketika ada kesalahan.
Ketika pengguna membuat kesalahan mengedit formulir, kita perlu memastikan bahwa formulir diputar ulang dengan pesan kesalahan informatif yang memandu mereka untuk memperbaikinya. Ini termasuk kasus di mana pengguna akhir memposting input yang salah (misalnya: string tanggal salah bentuk), serta kasus di mana format input valid tetapi ada pelanggaran aturan bisnis. Ketika kesalahan terjadi, formulir harus mempertahankan data input yang awalnya dimasukkan pengguna sehingga mereka tidak perlu mengisi ulang perubahan mereka secara manual. Proses ini harus diulang sebanyak yang diperlukan sampai formulir berhasil diselesaikan.
ASP.NET MVC menyertakan beberapa fitur bawaan yang bagus yang memudahkan penanganan kesalahan dan bentuk redisplay. Untuk melihat fitur-fitur ini dalam tindakan, mari kita perbarui metode tindakan Edit kami dengan kode berikut:
//
// POST: /Dinners/Edit/2
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues) {
Dinner dinner = dinnerRepository.GetDinner(id);
try {
UpdateModel(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id=dinner.DinnerID });
}
catch {
foreach (var issue in dinner.GetRuleViolations()) {
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
return View(dinner);
}
}
Kode di atas mirip dengan implementasi kami sebelumnya - kecuali bahwa kami sekarang membungkus blok penanganan kesalahan try/catch di sekitar pekerjaan kami. Jika pengecualian terjadi baik saat memanggil UpdateModel(), atau ketika kami mencoba dan menyimpan DinnerRepository (yang akan menimbulkan pengecualian jika objek Makan Malam yang kami coba simpan tidak valid karena pelanggaran aturan dalam model kami), blok penanganan kesalahan tangkapan kami akan dijalankan. Di dalamnya kita mengulangi setiap pelanggaran aturan yang ada di objek Makan Malam dan menambahkannya ke objek ModelState (yang akan segera kita bahas). Kami kemudian memutar ulang tampilan.
Untuk melihat pekerjaan ini mari kita jalankan kembali aplikasi, edit Makan Malam, dan ubah agar memiliki Judul kosong, EventDate "BOGUS", dan gunakan nomor telepon Inggris dengan nilai negara/wilayah AS. Ketika kami menekan tombol "Simpan" metode HTTP POST Edit kami tidak akan dapat menyimpan Makan Malam (karena ada kesalahan) dan akan memutar ulang formulir:
Aplikasi kami memiliki pengalaman kesalahan yang layak. Elemen teks dengan input yang tidak valid disorot dengan warna merah, dan pesan kesalahan validasi ditampilkan kepada pengguna akhir tentang mereka. Formulir ini juga mempertahankan data input yang awalnya dimasukkan pengguna - sehingga mereka tidak perlu mengisi ulang apa pun.
Bagaimana, Anda mungkin bertanya, apakah ini terjadi? Bagaimana kotak teks Judul, EventDate, dan ContactPhone menyoroti diri mereka dalam warna merah dan mengetahui output nilai pengguna yang awalnya dimasukkan? Dan bagaimana pesan kesalahan ditampilkan dalam daftar di bagian atas? Kabar baiknya adalah bahwa ini tidak terjadi dengan sihir - melainkan karena kami menggunakan beberapa fitur MVC ASP.NET bawaan yang memudahkan validasi input dan skenario penanganan kesalahan.
Memahami ModelState dan Metode Pembantu HTML Validasi
Kelas pengontrol memiliki koleksi properti "ModelState" yang menyediakan cara untuk menunjukkan bahwa ada kesalahan dengan objek model yang diteruskan ke Tampilan. Entri kesalahan dalam koleksi ModelState mengidentifikasi nama properti model dengan masalah (misalnya: "Judul", "EventDate", atau "ContactPhone"), dan izinkan pesan kesalahan yang ramah manusia ditentukan (misalnya: "Judul diperlukan").
Metode pembantu UpdateModel() secara otomatis mengisi koleksi ModelState saat mengalami kesalahan saat mencoba menetapkan nilai formulir ke properti pada objek model. Misalnya, properti EventDate objek Makan Malam kami berjenis DateTime. Ketika metode UpdateModel() tidak dapat menetapkan nilai string "BOGUS" ke dalam skenario di atas, metode UpdateModel() menambahkan entri ke koleksi ModelState yang menunjukkan kesalahan penugasan telah terjadi dengan properti tersebut.
Pengembang juga dapat menulis kode untuk secara eksplisit menambahkan entri kesalahan ke dalam koleksi ModelState seperti yang kami lakukan di bawah ini dalam blok penanganan kesalahan "tangkapan", yang mengisi koleksi ModelState dengan entri berdasarkan Pelanggaran Aturan aktif di objek Makan Malam:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues) {
Dinner dinner = dinnerRepository.GetDinner(id);
try {
UpdateModel(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id=dinner.DinnerID });
}
catch {
foreach (var issue in dinner.GetRuleViolations()) {
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
return View(dinner);
}
}
Integrasi Pembantu Html dengan ModelState
Metode pembantu HTML - seperti Html.TextBox() - periksa koleksi ModelState saat merender output. Jika ada kesalahan untuk item, mereka merender nilai yang dimasukkan pengguna dan kelas kesalahan CSS.
Misalnya, dalam tampilan "Edit" kami, kami menggunakan metode pembantu Html.TextBox() untuk merender EventDate objek Makan Malam kami:
<%= Html.TextBox("EventDate", String.Format("{0:g}", Model.EventDate)) %>
Ketika tampilan dirender dalam skenario kesalahan, metode Html.TextBox() memeriksa koleksi ModelState untuk melihat apakah ada kesalahan yang terkait dengan properti "EventDate" dari objek Makan Malam kami. Ketika menentukan bahwa ada kesalahan, ia merender input pengguna yang dikirimkan ("BOGUS") sebagai nilai, dan menambahkan kelas kesalahan css ke <jenis input="kotak teks"/> markup yang dihasilkannya:
<input class="input-validation-error"id="EventDate" name="EventDate" type="text" value="BOGUS"/>
Anda dapat menyesuaikan tampilan kelas kesalahan css agar terlihat sesuai keinginan Anda. Kelas kesalahan CSS default – "input-validation-error" – didefinisikan dalam lembar gaya \content\site.css dan terlihat seperti di bawah ini:
.input-validation-error
{
border: 1px solid #ff0000;
background-color: #ffeeee;
}
Aturan CSS inilah yang menyebabkan elemen input kami yang tidak valid disorot seperti di bawah ini:
Metode Pembantu Html.ValidationMessage()
Metode pembantu Html.ValidationMessage() dapat digunakan untuk menghasilkan pesan kesalahan ModelState yang terkait dengan properti model tertentu:
<%= Html.ValidationMessage("EventDate")%>
Output kode di atas: <span class="field-validation-error"> Nilai 'BOGUS' tidak valid</rentang>
Metode pembantu Html.ValidationMessage() juga mendukung parameter kedua yang memungkinkan pengembang untuk mengambil alih pesan teks kesalahan yang ditampilkan:
<%= Html.ValidationMessage("EventDate","*") %>
Output kode di atas: <rentang class="field-validation-error">*</span> alih-alih teks kesalahan default saat terjadi kesalahan untuk properti EventDate.
Metode Pembantu Html.ValidationSummary()
Metode pembantu Html.ValidationSummary() dapat digunakan untuk merender pesan kesalahan ringkasan, disertai dengan <daftar ul><li/></ul> dari semua pesan kesalahan terperinci dalam koleksi ModelState:
Metode pembantu Html.ValidationSummary() mengambil parameter string opsional – yang menentukan pesan kesalahan ringkasan untuk ditampilkan di atas daftar kesalahan terperinci:
<%= Html.ValidationSummary("Please correct the errors and try again.") %>
Anda dapat secara opsional menggunakan CSS untuk mengambil alih seperti apa daftar kesalahan tersebut.
Menggunakan Metode Pembantu AddRuleViolations
Implementasi HTTP-POST Edit awal kami menggunakan pernyataan foreach dalam blok tangkapannya untuk mengulang Pelanggaran Aturan objek Makan Malam dan menambahkannya ke koleksi ModelState pengontrol:
catch {
foreach (var issue in dinner.GetRuleViolations()) {
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
return View(dinner);
}
Kita dapat membuat kode ini sedikit lebih bersih dengan menambahkan kelas "ControllerHelpers" ke proyek NerdDinner, dan menerapkan metode ekstensi "AddRuleViolations" di dalamnya yang menambahkan metode pembantu ke kelas ASP.NET MVC ModelStateDictionary. Metode ekstensi ini dapat merangkum logika yang diperlukan untuk mengisi ModelStateDictionary dengan daftar kesalahan RuleViolation:
public static class ControllerHelpers {
public static void AddRuleViolations(this ModelStateDictionary modelState, IEnumerable<RuleViolation> errors) {
foreach (RuleViolation issue in errors) {
modelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
}
}
Kami kemudian dapat memperbarui metode tindakan HTTP-POST Edit kami untuk menggunakan metode ekstensi ini untuk mengisi koleksi ModelState dengan Pelanggaran Aturan Makan Malam kami.
Selesaikan Implementasi Metode Tindakan Edit
Kode di bawah ini mengimplementasikan semua logika pengontrol yang diperlukan untuk skenario Edit kami:
//
// GET: /Dinners/Edit/2
public ActionResult Edit(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
return View(dinner);
}
//
// POST: /Dinners/Edit/2
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues) {
Dinner dinner = dinnerRepository.GetDinner(id);
try {
UpdateModel(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id=dinner.DinnerID });
}
catch {
ModelState.AddRuleViolations(dinner.GetRuleViolations());
return View(dinner);
}
}
Hal yang menyenangkan tentang implementasi Edit kami adalah bahwa tidak ada kelas Pengontrol kami atau templat Tampilan kami yang harus tahu apa pun tentang validasi tertentu atau aturan bisnis yang diberlakukan oleh model Makan Malam kami. Kami dapat menambahkan aturan tambahan ke model kami di masa mendatang dan tidak perlu membuat perubahan kode apa pun pada pengontrol atau tampilan kami agar dapat didukung. Ini memberi kami fleksibilitas untuk dengan mudah mengembangkan persyaratan aplikasi kami di masa depan dengan minimal perubahan kode.
Buat Dukungan
Kami telah selesai menerapkan perilaku "Edit" dari kelas DinnersController kami. Sekarang mari kita lanjutkan untuk mengimplementasikan dukungan "Buat" di atasnya - yang akan memungkinkan pengguna untuk menambahkan Makan Malam baru.
Metode Tindakan Pembuatan HTTP-GET
Kita akan mulai dengan menerapkan perilaku HTTP "GET" dari metode tindakan buat kita. Metode ini akan dipanggil ketika seseorang mengunjungi URL /Dinners/Create . Implementasi kami terlihat seperti:
//
// GET: /Dinners/Create
public ActionResult Create() {
Dinner dinner = new Dinner() {
EventDate = DateTime.Now.AddDays(7)
};
return View(dinner);
}
Kode di atas membuat objek Makan Malam baru, dan menetapkan properti EventDate-nya menjadi satu minggu di masa depan. Kemudian merender Tampilan yang didasarkan pada objek Makan Malam baru. Karena kami belum secara eksplisit meneruskan nama ke metode pembantu View(), itu akan menggunakan jalur default berbasis konvensi untuk menyelesaikan templat tampilan: /Views/Dinners/Create.aspx.
Sekarang mari kita buat templat tampilan ini. Kita dapat melakukan ini dengan mengklik kanan dalam metode buat tindakan dan memilih perintah menu konteks "Tambahkan Tampilan". Dalam dialog "Tambahkan Tampilan" kami akan menunjukkan bahwa kami meneruskan objek Makan Malam ke templat tampilan, dan memilih untuk merancang templat "Buat" secara otomatis:
Ketika kita mengklik tombol "Tambahkan", Visual Studio akan menyimpan tampilan "Create.aspx" berbasis perancah baru ke direktori "\Views\Dinners", dan membukanya di dalam IDE:
Mari kita buat beberapa perubahan pada file perancah "buat" default yang dihasilkan untuk kita, dan ubah agar terlihat seperti di bawah ini:
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
Host a Dinner
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
<h2>Host a Dinner</h2>
<%=Html.ValidationSummary("Please correct the errors and try again.") %>
<% using (Html.BeginForm()) {%>
<fieldset>
<p>
<label for="Title">Title:</label>
<%= Html.TextBox("Title") %>
<%= Html.ValidationMessage("Title", "*") %>
</p>
<p>
<label for="EventDate">EventDate:</label>
<%=Html.TextBox("EventDate") %>
<%=Html.ValidationMessage("EventDate", "*") %>
</p>
<p>
<label for="Description">Description:</label>
<%=Html.TextArea("Description") %>
<%=Html.ValidationMessage("Description", "*") %>
</p>
<p>
<label for="Address">Address:</label>
<%=Html.TextBox("Address") %>
<%=Html.ValidationMessage("Address", "*") %>
</p>
<p>
<label for="Country">Country:</label>
<%=Html.TextBox("Country") %>
<%=Html.ValidationMessage("Country", "*") %>
</p>
<p>
<label for="ContactPhone">ContactPhone:</label>
<%=Html.TextBox("ContactPhone") %>
<%=Html.ValidationMessage("ContactPhone", "*") %>
</p>
<p>
<label for="Latitude">Latitude:</label>
<%=Html.TextBox("Latitude") %>
<%=Html.ValidationMessage("Latitude", "*") %>
</p>
<p>
<label for="Longitude">Longitude:</label>
<%=Html.TextBox("Longitude") %>
<%=Html.ValidationMessage("Longitude", "*") %>
</p>
<p>
<input type="submit" value="Save"/>
</p>
</fieldset>
<% }
%>
</asp:Content>
Dan sekarang ketika kita menjalankan aplikasi kita dan mengakses URL "/Dinners/Create" di dalam browser itu akan merender UI seperti di bawah ini dari implementasi buat tindakan kami:
Menerapkan Metode Tindakan Buat HTTP-POST
Kami memiliki versi HTTP-GET dari metode tindakan Buat kami yang diimplementasikan. Ketika pengguna mengklik tombol "Simpan" ia melakukan posting formulir ke /Dinners/Create URL, dan mengirimkan nilai formulir input> HTML <menggunakan kata kerja HTTP POST.
Sekarang mari kita terapkan perilaku HTTP POST dari metode tindakan buat kita. Kita akan mulai dengan menambahkan metode tindakan "Buat" yang kelebihan beban ke DinnersController kita yang memiliki atribut "AcceptVerbs" di dalamnya yang menunjukkan metode ini menangani skenario HTTP POST:
//
// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create() {
...
}
Ada berbagai cara untuk mengakses parameter formulir yang diposting dalam metode "Buat" dengan dukungan HTTP-POST.
Salah satu pendekatannya adalah membuat objek Makan Malam baru dan kemudian menggunakan metode pembantu UpdateModel() (seperti yang kami lakukan dengan tindakan Edit) untuk mengisinya dengan nilai formulir yang diposting. Kami kemudian dapat menambahkannya ke DinnerRepository kami, mempertahankannya ke database, dan mengalihkan pengguna ke tindakan Detail kami untuk menunjukkan Makan Malam yang baru dibuat menggunakan kode di bawah ini:
//
// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create() {
Dinner dinner = new Dinner();
try {
UpdateModel(dinner);
dinnerRepository.Add(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new {id=dinner.DinnerID});
}
catch {
ModelState.AddRuleViolations(dinner.GetRuleViolations());
return View(dinner);
}
}
Atau, kita dapat menggunakan pendekatan di mana kita memiliki metode tindakan Create() kita mengambil objek Makan Malam sebagai parameter metode. ASP.NET MVC kemudian akan secara otomatis membuat instans objek Makan Malam baru untuk kami, mengisi propertinya menggunakan input formulir, dan meneruskannya ke metode tindakan kami:
//
//
// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Dinner dinner) {
if (ModelState.IsValid) {
try {
dinner.HostedBy = "SomeUser";
dinnerRepository.Add(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new {id = dinner.DinnerID });
}
catch {
ModelState.AddRuleViolations(dinner.GetRuleViolations());
}
}
return View(dinner);
}
Metode tindakan kami di atas memverifikasi bahwa objek Makan Malam telah berhasil diisi dengan nilai posting formulir dengan memeriksa properti ModelState.IsValid. Ini akan mengembalikan false jika ada masalah konversi input (misalnya: string "BOGUS" untuk properti EventDate), dan jika ada masalah, metode tindakan kami memutar ulang formulir.
Jika nilai input valid, maka metode tindakan mencoba menambahkan dan menyimpan Makan Malam baru ke DinnerRepository. Ini membungkus pekerjaan ini dalam blok try/catch dan menampilkan kembali formulir jika ada pelanggaran aturan bisnis (yang akan menyebabkan metode dinnerRepository.Save() menimbulkan pengecualian).
Untuk melihat perilaku penanganan kesalahan ini dalam tindakan, kami dapat meminta /Dinners/Create URL dan mengisi detail tentang Makan Malam baru. Input atau nilai yang salah akan menyebabkan formulir buat diputar ulang dengan kesalahan yang disorot seperti di bawah ini:
Perhatikan bagaimana formulir Buat kami mematuhi validasi dan aturan bisnis yang sama persis dengan formulir Edit kami. Ini karena validasi dan aturan bisnis kami didefinisikan dalam model, dan tidak disematkan dalam UI atau pengontrol aplikasi. Ini berarti kita nantinya dapat mengubah/mengembangkan validasi atau aturan bisnis kita di satu tempat dan membuatnya berlaku di seluruh aplikasi kita. Kami tidak perlu mengubah kode apa pun baik dalam metode tindakan Edit atau Buat kami untuk secara otomatis mematuhi aturan atau modifikasi baru pada yang sudah ada.
Ketika kami memperbaiki nilai input dan mengklik tombol "Simpan" lagi, tambahan kami ke DinnerRepository akan berhasil, dan Makan Malam baru akan ditambahkan ke database. Kami kemudian akan dialihkan ke URL /Dinners/Details/[id] – di mana kami akan disajikan dengan detail tentang Makan Malam yang baru dibuat:
Hapus Dukungan
Sekarang mari kita tambahkan dukungan "Hapus" ke DinnersController kami.
Metode Tindakan Penghapusan HTTP-GET
Kita akan mulai dengan menerapkan perilaku HTTP GET dari metode tindakan penghapusan kita. Metode ini akan dipanggil ketika seseorang mengunjungi URL /Dinners/Delete/[id ]. Di bawah ini adalah implementasinya:
//
// HTTP GET: /Dinners/Delete/1
public ActionResult Delete(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (dinner == null)
return View("NotFound");
else
return View(dinner);
}
Metode tindakan mencoba mengambil Makan Malam untuk dihapus. Jika Makan Malam ada, itu merender Tampilan berdasarkan objek Makan Malam. Jika objek tidak ada (atau telah dihapus) objek mengembalikan Tampilan yang merender templat tampilan "NotFound" yang kami buat sebelumnya untuk metode tindakan "Detail" kami.
Kita dapat membuat templat tampilan "Hapus" dengan mengklik kanan dalam metode tindakan Hapus dan memilih perintah menu konteks "Tambahkan Tampilan". Dalam dialog "Tambahkan Tampilan" kami akan menunjukkan bahwa kami meneruskan objek Makan Malam ke templat tampilan kami sebagai modelnya, dan memilih untuk membuat templat kosong:
Ketika kami mengklik tombol "Tambahkan", Visual Studio akan menambahkan file templat tampilan "Delete.aspx" baru untuk kami dalam direktori "\Views\Dinners" kami. Kami akan menambahkan beberapa HTML dan kode ke templat untuk mengimplementasikan layar konfirmasi penghapusan seperti di bawah ini:
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
Delete Confirmation: <%=Html.Encode(Model.Title) %>
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
<h2>
Delete Confirmation
</h2>
<div>
<p>Please confirm you want to cancel the dinner titled:
<i> <%=Html.Encode(Model.Title) %>? </i>
</p>
</div>
<% using (Html.BeginForm()) { %>
<input name="confirmButton" type="submit" value="Delete" />
<% } %>
</asp:Content>
Kode di atas menampilkan judul Makan Malam yang akan dihapus, dan menghasilkan <elemen formulir> yang melakukan POST ke URL /Dinners/Delete/[id] jika pengguna akhir mengklik tombol "Hapus" di dalamnya.
Ketika kami menjalankan aplikasi kami dan mengakses URL "/Dinners/Delete/[id]" untuk objek Dinner yang valid, url tersebut merender UI seperti di bawah ini:
| Topik Samping: Mengapa kita melakukan POST? |
|---|
| Anda mungkin bertanya - mengapa kita melalui upaya membuat <formulir> dalam layar konfirmasi Hapus kami? Mengapa tidak hanya menggunakan hyperlink standar untuk menautkan ke metode tindakan yang melakukan operasi penghapusan aktual? Alasannya adalah karena kita ingin berhati-hati untuk menjaga terhadap perayap web dan mesin pencari yang menemukan URL kita dan secara tidak sengaja menyebabkan data dihapus ketika mereka mengikuti tautan. URL berbasis HTTP-GET dianggap "aman" untuk diakses/dirayapi, dan seharusnya tidak mengikuti URL HTTP-POST. Aturan yang baik adalah memastikan Anda selalu menempatkan operasi pengubahan data atau destruktif di balik permintaan HTTP-POST. |
Menerapkan Metode Tindakan Penghapusan HTTP-POST
Kami sekarang memiliki versi HTTP-GET dari metode tindakan Hapus kami yang diimplementasikan yang menampilkan layar konfirmasi penghapusan. Ketika pengguna akhir mengklik tombol "Hapus" itu akan melakukan posting formulir ke URL /Dinners/[id ].
Sekarang mari kita terapkan perilaku HTTP "POST" dari metode tindakan hapus menggunakan kode di bawah ini:
//
// HTTP POST: /Dinners/Delete/1
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(int id, string confirmButton) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (dinner == null)
return View("NotFound");
dinnerRepository.Delete(dinner);
dinnerRepository.Save();
return View("Deleted");
}
Versi HTTP-POST dari metode tindakan Hapus kami mencoba mengambil objek makan malam untuk dihapus. Jika tidak dapat menemukannya (karena telah dihapus) templat "NotFound" kami akan dirender. Jika menemukan Makan Malam, itu menghapusnya dari DinnerRepository. Kemudian merender templat "Dihapus".
Untuk mengimplementasikan templat "Dihapus" kita akan mengklik kanan dalam metode tindakan dan memilih menu konteks "Tambahkan Tampilan". Kami akan menamai tampilan kami "Dihapus" dan memilikinya menjadi templat kosong (dan tidak mengambil objek model yang ditik dengan kuat). Kami kemudian akan menambahkan beberapa konten HTML ke dalamnya:
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
Dinner Deleted
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server">
<h2>Dinner Deleted</h2>
<div>
<p>Your dinner was successfully deleted.</p>
</div>
<div>
<p><a href="/dinners">Click for Upcoming Dinners</a></p>
</div>
</asp:Content>
Dan sekarang ketika kami menjalankan aplikasi kami dan mengakses URL "/Dinners/Delete/[id]" untuk objek Makan Malam yang valid, itu akan merender layar konfirmasi penghapusan Makan Malam kami seperti di bawah ini:
Ketika kita klik tombol "Hapus" itu akan melakukan HTTP-POST ke URL /Dinners/Delete/[id] , yang akan menghapus Makan Malam dari database kami, dan menampilkan templat tampilan "Dihapus" kami:
Keamanan Pengikatan Model
Kami telah membahas dua cara berbeda untuk menggunakan fitur pengikatan model bawaan ASP.NET MVC. Yang pertama menggunakan metode UpdateModel() untuk memperbarui properti pada objek model yang ada, dan yang kedua menggunakan dukungan MVC ASP.NET untuk meneruskan objek model sebagai parameter metode tindakan. Kedua teknik ini sangat kuat dan sangat berguna.
Kekuatan ini juga membawa tanggung jawab. Penting untuk selalu paranoid tentang keamanan saat menerima input pengguna apa pun, dan ini juga berlaku saat mengikat objek untuk membentuk input. Anda harus berhati-hati untuk selalu mengodekan HTML nilai apa pun yang dimasukkan pengguna untuk menghindari serangan injeksi HTML dan JavaScript, dan berhati-hatilah terhadap serangan injeksi SQL (catatan: kami menggunakan LINQ ke SQL untuk aplikasi kami, yang secara otomatis mengodekan parameter untuk mencegah jenis serangan ini). Anda tidak boleh mengandalkan validasi sisi klien saja, dan selalu menggunakan validasi sisi server untuk melindungi peretas yang mencoba mengirimi Anda nilai palsu.
Satu item keamanan tambahan untuk memastikan Anda memikirkan saat menggunakan fitur pengikatan ASP.NET MVC adalah cakupan objek yang Anda ikat. Secara khusus, Anda ingin memastikan Anda memahami implikasi keamanan properti yang Anda izinkan untuk terikat, dan pastikan Anda hanya mengizinkan properti yang benar-benar harus diperbarui oleh pengguna akhir untuk diperbarui.
Secara default, metode UpdateModel() akan mencoba memperbarui semua properti pada objek model yang cocok dengan nilai parameter formulir masuk. Demikian juga, objek yang diteruskan sebagai parameter metode tindakan juga secara default dapat mengatur semua propertinya melalui parameter formulir.
Mengunci pengikatan berdasarkan per penggunaan
Anda dapat mengunci kebijakan pengikatan berdasarkan per penggunaan dengan menyediakan "sertakan daftar" properti eksplisit yang dapat diperbarui. Ini dapat dilakukan dengan meneruskan parameter array string tambahan ke metode UpdateModel() seperti di bawah ini:
string[] allowedProperties = new[]{ "Title","Description",
"ContactPhone", "Address",
"EventDate", "Latitude",
"Longitude"};
UpdateModel(dinner, allowedProperties);
Objek yang diteruskan sebagai parameter metode tindakan juga mendukung atribut [Bind] yang memungkinkan "sertakan daftar" properti yang diizinkan ditentukan seperti di bawah ini:
//
// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create( [Bind(Include="Title,Address")] Dinner dinner ) {
...
}
Mengunci pengikatan berdasarkan jenis
Anda juga dapat mengunci aturan pengikatan berdasarkan per jenis. Ini memungkinkan Anda menentukan aturan pengikatan sekali, lalu menerapkannya dalam semua skenario (termasuk skenario parameter UpdateModel dan metode tindakan) di semua pengontrol dan metode tindakan.
Anda dapat menyesuaikan aturan pengikatan per jenis dengan menambahkan atribut [Bind] ke jenis, atau dengan mendaftarkannya dalam file Global.asax aplikasi (berguna untuk skenario di mana Anda tidak memiliki jenis). Anda kemudian dapat menggunakan properti Sertakan dan Kecualikan atribut Bind untuk mengontrol properti mana yang dapat diikat untuk kelas atau antarmuka tertentu.
Kami akan menggunakan teknik ini untuk kelas Makan Malam di aplikasi NerdDinner kami, dan menambahkan atribut [Bind] ke dalamnya yang membatasi daftar properti yang dapat diikat ke yang berikut:
[Bind(Include="Title,Description,EventDate,Address,Country,ContactPhone,Latitude,Longitude")]
public partial class Dinner {
...
}
Perhatikan bahwa kami tidak mengizinkan koleksi RSVP dimanipulasi melalui pengikatan, kami juga tidak mengizinkan properti DinnerID atau HostedBy diatur melalui pengikatan. Untuk alasan keamanan, kami hanya akan memanipulasi properti tertentu ini menggunakan kode eksplisit dalam metode tindakan kami.
Wrap-Up CRUD
ASP.NET MVC menyertakan sejumlah fitur bawaan yang membantu menerapkan skenario posting formulir. Kami menggunakan berbagai fitur ini untuk memberikan dukungan UI CRUD di atas DinnerRepository kami.
Kami menggunakan pendekatan yang berfokus pada model untuk mengimplementasikan aplikasi kami. Ini berarti bahwa semua validasi dan logika aturan bisnis kami didefinisikan dalam lapisan model kami - dan bukan dalam pengontrol atau tampilan kami. Baik kelas Pengontrol maupun templat Tampilan kami tidak tahu apa-apa tentang aturan bisnis tertentu yang diberlakukan oleh kelas model Makan Malam kami.
Ini akan menjaga arsitektur aplikasi kami tetap bersih dan membuatnya lebih mudah untuk diuji. Kami dapat menambahkan aturan bisnis tambahan ke lapisan model kami di masa mendatang dan tidak perlu membuat perubahan kode apa pun pada Pengontrol atau Tampilan kami agar dapat didukung. Ini akan memberi kita banyak kelincahan untuk berkembang dan mengubah aplikasi kita di masa depan.
DinnersController kami sekarang mengaktifkan daftar/detail Makan Malam, serta membuat, mengedit, dan menghapus dukungan. Kode lengkap untuk kelas dapat ditemukan di bawah ini:
public class DinnersController : Controller {
DinnerRepository dinnerRepository = new DinnerRepository();
//
// GET: /Dinners/
public ActionResult Index() {
var dinners = dinnerRepository.FindUpcomingDinners().ToList();
return View(dinners);
}
//
// GET: /Dinners/Details/2
public ActionResult Details(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (dinner == null)
return View("NotFound");
else
return View(dinner);
}
//
// GET: /Dinners/Edit/2
public ActionResult Edit(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
return View(dinner);
}
//
// POST: /Dinners/Edit/2
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues) {
Dinner dinner = dinnerRepository.GetDinner(id);
try {
UpdateModel(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new { id= dinner.DinnerID });
}
catch {
ModelState.AddRuleViolations(dinner.GetRuleViolations());
return View(dinner);
}
}
//
// GET: /Dinners/Create
public ActionResult Create() {
Dinner dinner = new Dinner() {
EventDate = DateTime.Now.AddDays(7)
};
return View(dinner);
}
//
// POST: /Dinners/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Dinner dinner) {
if (ModelState.IsValid) {
try {
dinner.HostedBy = "SomeUser";
dinnerRepository.Add(dinner);
dinnerRepository.Save();
return RedirectToAction("Details", new{id=dinner.DinnerID});
}
catch {
ModelState.AddRuleViolations(dinner.GetRuleViolations());
}
}
return View(dinner);
}
//
// HTTP GET: /Dinners/Delete/1
public ActionResult Delete(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (dinner == null)
return View("NotFound");
else
return View(dinner);
}
//
// HTTP POST: /Dinners/Delete/1
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(int id, string confirmButton) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (dinner == null)
return View("NotFound");
dinnerRepository.Delete(dinner);
dinnerRepository.Save();
return View("Deleted");
}
}
Langkah Selanjutnya
Kami sekarang memiliki implementasi dukungan CRUD dasar (Buat, Baca, Perbarui, dan Hapus) dalam kelas DinnersController kami.
Sekarang mari kita lihat bagaimana kita dapat menggunakan kelas ViewData dan ViewModel untuk mengaktifkan UI yang lebih kaya pada formulir kita.