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 7 dari tutorial aplikasi "NerdDinner" gratis yang memandu cara membangun aplikasi web kecil, tetapi lengkap menggunakan ASP.NET MVC 1.
Langkah 7 melihat cara kita dapat menerapkan "Prinsip DRY" dalam templat tampilan kita untuk menghilangkan duplikasi kode, menggunakan templat tampilan parsial dan halaman master.
Jika Anda menggunakan ASP.NET MVC 3, kami sarankan Anda mengikuti tutorial Memulai MVC 3 atau MVC Music Store .
NerdDinner Langkah 7: Halaman Parsial dan Master
Salah satu filosofi desain ASP.NET yang dirangkul MVC adalah prinsip "Jangan Ulangi Diri" (biasa disebut sebagai "DRY"). Desain DRY membantu menghilangkan duplikasi kode dan logika, yang pada akhirnya membuat aplikasi lebih cepat dibangun dan lebih mudah dipertahankan.
Kami telah melihat prinsip DRY diterapkan dalam beberapa skenario NerdDinner kami. Beberapa contoh: logika validasi kami diimplementasikan dalam lapisan model kami, yang memungkinkannya diberlakukan di kedua skenario edit dan buat di pengontrol kami; kami menggunakan kembali templat tampilan "NotFound" di seluruh metode tindakan Edit, Detail, dan Hapus; kami menggunakan pola penamaan konvensi dengan templat tampilan kami, yang menghilangkan kebutuhan untuk secara eksplisit menentukan nama ketika kami memanggil metode pembantu View() ; dan kami menggunakan kembali kelas DinnerFormViewModel untuk skenario tindakan Edit dan Buat.
Sekarang mari kita lihat cara kita dapat menerapkan "Prinsip DRY" dalam templat tampilan kita untuk menghilangkan duplikasi kode di sana juga.
Mengunjungi kembali Templat Edit dan Buat Tampilan kami
Saat ini kami menggunakan dua templat tampilan yang berbeda - "Edit.aspx" dan "Create.aspx" - untuk menampilkan antarmuka pengguna formulir Makan Malam kami. Perbandingan visual cepat dari mereka menyoroti seberapa mirip mereka. Di bawah ini adalah seperti apa formulir buat:
Dan inilah tampilan formulir "Edit" kami:
Tidak banyak perbedaan yang ada? Selain judul dan teks header, tata letak formulir dan kontrol input identik.
Jika kita membuka templat tampilan "Edit.aspx" dan "Create.aspx" kita akan menemukan bahwa templat tersebut berisi tata letak formulir yang identik dan kode kontrol input. Duplikasi ini berarti kami akhirnya harus membuat perubahan dua kali kapan saja kami memperkenalkan atau mengubah properti Makan Malam baru - yang tidak baik.
Menggunakan Templat Tampilan Parsial
ASP.NET MVC mendukung kemampuan untuk menentukan templat "tampilan parsial" yang dapat digunakan untuk merangkum logika penyajian tampilan untuk sub-bagian halaman. "Parsial" menyediakan cara yang berguna untuk menentukan logika penyajian tampilan sekali, lalu menggunakannya kembali di beberapa tempat di seluruh aplikasi.
Untuk membantu "DRY-up" duplikasi templat tampilan Edit.aspx dan Create.aspx kami, kami dapat membuat templat tampilan parsial bernama "DinnerForm.ascx" yang merangkum tata letak formulir dan elemen input yang umum untuk keduanya. Kami akan melakukan ini dengan mengklik kanan pada direktori /Views/Dinners kami dan memilih perintah menu "Add-View>":
Ini akan menampilkan dialog "Tambahkan Tampilan". Kami akan memberi nama tampilan baru yang ingin kami buat "DinnerForm", pilih kotak centang "Buat tampilan parsial" dalam dialog, dan menunjukkan bahwa kami akan meneruskannya kelas DinnerFormViewModel:
Ketika kita mengklik tombol "Tambahkan", Visual Studio akan membuat templat tampilan "DinnerForm.ascx" baru untuk kita dalam direktori "\Views\Dinners".
Kami kemudian dapat menyalin/menempelkan tata letak formulir duplikat /kode kontrol input dari templat tampilan Edit.aspx/ Create.aspx kami ke templat tampilan parsial "DinnerForm.ascx" baru kami:
<%= Html.ValidationSummary("Please correct the errors and try again.") %>
<% using (Html.BeginForm()) { %>
<fieldset>
<p>
<label for="Title">Dinner Title:</label>
<%= Html.TextBox("Title", Model.Dinner.Title) %>
<%=Html.ValidationMessage("Title", "*") %>
</p>
<p>
<label for="EventDate">Event Date:</label>
<%= Html.TextBox("EventDate", Model.Dinner.EventDate) %>
<%= Html.ValidationMessage("EventDate", "*") %>
</p>
<p>
<label for="Description">Description:</label>
<%= Html.TextArea("Description", Model.Dinner.Description) %>
<%= Html.ValidationMessage("Description", "*") %>
</p>
<p>
<label for="Address">Address:</label>
<%= Html.TextBox("Address", Model.Dinner.Address) %>
<%= Html.ValidationMessage("Address", "*") %>
</p>
<p>
<label for="Country">Country:</label>
<%= Html.DropDownList("Country", Model.Countries) %>
<%= Html.ValidationMessage("Country", "*") %>
</p>
<p>
<label for="ContactPhone">Contact Phone #:</label>
<%= Html.TextBox("ContactPhone", Model.Dinner.ContactPhone) %>
<%= Html.ValidationMessage("ContactPhone", "*") %>
</p>
<p>
<input type="submit" value="Save"/>
</p>
</fieldset>
<% } %>
Kita kemudian dapat memperbarui templat tampilan Edit dan Buat untuk memanggil templat parsial DinnerForm dan menghilangkan duplikasi formulir. Kita dapat melakukan ini dengan memanggil Html.RenderPartial("DinnerForm") dalam templat tampilan kita:
Create.aspx
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
Host a Dinner
</asp:Content>
<asp:Content ID="Create" ContentPlaceHolderID="MainContent" runat="server">
<h2>Host a Dinner</h2>
<% Html.RenderPartial("DinnerForm"); %>
</asp:Content>
Edit.aspx
<asp:Content ID="Title" ContentPlaceHolderID="TitleContent" runat="server">
Edit: <%=Html.Encode(Model.Dinner.Title) %>
</asp:Content>
<asp:Content ID="Edit" ContentPlaceHolderID="MainContent" runat="server">
<h2>Edit Dinner</h2>
<% Html.RenderPartial("DinnerForm"); %>
</asp:Content>
Anda dapat secara eksplisit memenuhi syarat jalur templat parsial yang Anda inginkan saat memanggil Html.RenderPartial (misalnya: ~Views/Dinners/DinnerForm.ascx"). Namun, dalam kode kami di atas, kami memanfaatkan pola penamaan berbasis konvensi dalam ASP.NET MVC, dan hanya menentukan "DinnerForm" sebagai nama parsial untuk dirender. Ketika kita melakukan ini ASP.NET MVC akan melihat terlebih dahulu di direktori tampilan berbasis konvensi (untuk DinnersController ini adalah /Views/Dinners). Jika tidak menemukan templat parsial di sana, templat tersebut akan mencarinya di direktori /Views/Shared.
Ketika Html.RenderPartial() dipanggil hanya dengan nama tampilan parsial, ASP.NET MVC akan meneruskan ke tampilan parsial objek kamus Model dan ViewData yang sama yang digunakan oleh templat tampilan panggilan. Atau, ada versi Html.RenderPartial() yang kelebihan beban yang memungkinkan Anda meneruskan objek Model alternatif dan/atau kamus ViewData untuk tampilan parsial yang akan digunakan. Ini berguna untuk skenario di mana Anda hanya ingin meneruskan subset Model/ViewModel lengkap.
| Topik Samping: Mengapa <% %> bukan <%= %>? |
|---|
| Salah satu hal halus yang mungkin telah Anda perhatikan dengan kode di atas adalah bahwa kita menggunakan <blok % %> alih-alih <blok %= %> saat memanggil Html.RenderPartial(). <%= %> blok dalam ASP.NET menunjukkan bahwa pengembang ingin merender nilai yang ditentukan (misalnya: <%= "Halo" %> akan merender "Halo"). <% %> blok sebagai gantinya menunjukkan bahwa pengembang ingin menjalankan kode, dan bahwa setiap output yang dirender di dalamnya harus dilakukan secara eksplisit (misalnya: <% Response.Write("Hello") %>. Alasan kami menggunakan <blok % %> dengan kode Html.RenderPartial kami di atas adalah karena metode Html.RenderPartial() tidak mengembalikan string, dan sebaliknya menghasilkan konten langsung ke aliran output templat tampilan panggilan. Ini dilakukan untuk alasan efisiensi performa, dan dengan melakukannya menghindari kebutuhan untuk membuat objek string sementara (berpotensi sangat besar). Ini mengurangi penggunaan memori dan meningkatkan throughput aplikasi secara keseluruhan. Salah satu kesalahan umum saat menggunakan Html.RenderPartial() adalah lupa menambahkan titik koma di akhir panggilan ketika berada dalam <blok % %> . Misalnya, kode ini akan menyebabkan kesalahan kompilator: <% Html.RenderPartial("DinnerForm") %> Anda sebaliknya perlu menulis: <% Html.RenderPartial("DinnerForm"); %> Ini karena <% %> blok adalah pernyataan kode mandiri, dan ketika menggunakan pernyataan kode C# perlu dihentikan dengan titik koma. |
Menggunakan Templat Tampilan Parsial untuk Mengklarifikasi Kode
Kami membuat templat tampilan parsial "DinnerForm" untuk menghindari logika penyajian tampilan duplikat di beberapa tempat. Ini adalah alasan paling umum untuk membuat templat tampilan parsial.
Terkadang masih masuk akal untuk menciptakan tampilan parsial bahkan ketika mereka hanya dipanggil di satu tempat. Templat tampilan yang sangat rumit seringkali dapat menjadi jauh lebih mudah dibaca ketika logika penyajian tampilan mereka diekstraksi dan dipartisi menjadi satu atau beberapa templat parsial bernama baik.
Misalnya, pertimbangkan cuplikan kode di bawah ini dari file Site.master dalam proyek kami (yang akan segera kita lihat). Kode relatif mudah dibaca - sebagian karena logika untuk menampilkan tautan masuk/keluar di kanan atas layar dienkapsulasi dalam parsial "LogOnUserControl":
<div id="header">
<div id="title">
<h1>My MVC Application</h1>
</div>
<div id="logindisplay">
<% Html.RenderPartial("LogOnUserControl"); %>
</div>
<div id="menucontainer">
<ul id="menu">
<li><%=Html.ActionLink("Home", "Index", "Home")%></li>
<li><%=Html.ActionLink("About", "About", "Home")%></li>
</ul>
</div>
</div>
Setiap kali Anda merasa bingung mencoba memahami markup html/kode dalam view-template, pertimbangkan apakah itu tidak akan lebih jelas jika beberapa diekstraksi dan direfaktorkan ke dalam tampilan parsial bernama baik.
Halaman Induk
Selain mendukung tampilan parsial, ASP.NET MVC juga mendukung kemampuan untuk membuat templat "halaman master" yang dapat digunakan untuk menentukan tata letak umum dan html tingkat atas situs. Kontrol tempat penampung konten kemudian dapat ditambahkan ke halaman master untuk mengidentifikasi wilayah yang dapat diganti yang dapat ditimpa atau "diisi" berdasarkan tampilan. Ini menyediakan cara yang sangat efektif (dan DRY) untuk menerapkan tata letak umum di seluruh aplikasi.
Secara default, proyek ASP.NET MVC baru memiliki templat halaman master yang secara otomatis ditambahkan ke dalamnya. Halaman master ini bernama "Site.master" dan berada dalam folder \Views\Shared\:
File Site.master default terlihat seperti di bawah ini. Ini mendefinisikan html luar situs, bersama dengan menu untuk navigasi di bagian atas. Ini berisi dua kontrol tempat penampung konten yang dapat diganti - satu untuk judul, dan yang lainnya di mana konten utama halaman harus diganti:
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>
<asp:ContentPlaceHolder ID="TitleContent" runat="server" />
</title>
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="page">
<div id="header">
<div id="title">
<h1>My MVC Application</h1>
</div>
<div id="logindisplay">
<% Html.RenderPartial("LogOnUserControl"); %>
</div>
<div id="menucontainer">
<ul id="menu">
<li><%=Html.ActionLink("Home", "Index", "Home")%></li>
<li><%=Html.ActionLink("About", "About", "Home")%></li>
</ul>
</div>
</div>
<div id="main">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
</div>
</body>
</html>
Semua templat tampilan yang telah kami buat untuk aplikasi NerdDinner kami ("Daftar", "Detail", "Edit", "Buat", "TidakFound", dll) telah didasarkan pada templat Site.master ini. Ini ditunjukkan melalui atribut "MasterPageFile" yang ditambahkan secara default ke direktif % @ Halaman %> teratas <saat kami membuat tampilan menggunakan dialog "Tambahkan Tampilan":
<%@ Page Inherits="System.Web.Mvc.ViewPage<NerdDinner.Controllers.DinnerViewModel>" MasterPageFile="~/Views/Shared/Site.Master" %>
Apa artinya ini adalah bahwa kita dapat mengubah konten Site.master, dan memiliki perubahan secara otomatis diterapkan dan digunakan ketika kita merender salah satu templat tampilan kita.
Mari kita perbarui bagian header Site.master kami sehingga header aplikasi kami adalah "NerdDinner" alih-alih "Aplikasi MVC Saya". Mari kita perbarui juga menu navigasi kita sehingga tab pertama adalah "Temukan Makan Malam" (ditangani oleh metode tindakan Indeks() HomeController, dan mari kita tambahkan tab baru yang disebut "Host a Dinner" (ditangani oleh metode tindakan Buat() DinnersController):
<div id="header">
<div id="title">
<h1>NerdDinner</h1>
</div>
<div id="logindisplay">
<% Html.RenderPartial("LoginStatus"); %>
</div>
<div id="menucontainer">
<ul id="menu">
<li><%=Html.ActionLink("Find Dinner", "Index", "Home")%></li>
<li><%=Html.ActionLink("Host Dinner", "Create", "Dinners")%></li>
<li><%=Html.ActionLink("About", "About", "Home")%></li>
</ul>
</div>
</div>
Ketika kita menyimpan file Site.master dan merefresh browser kita, kita akan melihat perubahan header kita muncul di semua tampilan dalam aplikasi kita. Contohnya:
Dan dengan URL /Dinners/Edit/[id] :
Langkah Selanjutnya
Halaman parsial dan master menyediakan opsi yang sangat fleksibel yang memungkinkan Anda mengatur tampilan dengan bersih. Anda akan menemukan bahwa mereka membantu Anda menghindari duplikat menampilkan konten/kode, dan membuat templat tampilan Anda lebih mudah dibaca dan dikelola.
Sekarang mari kita lihat kembali skenario daftar yang kita bangun sebelumnya dan aktifkan dukungan penomoran yang dapat diskalakan.