我們在Asp.net mvc的view開發過程中,如果不注意可能會寫大量的重複的代碼。這篇文章介紹3種方式重構View的代碼,來減少View中的重複代碼。
1、母板頁
在Asp.net mvc中保留了母板頁的使用,我們可以使用母板頁對我們的網站進行布局。看下面母板頁的代碼:
<%@ 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="http://www.cnblogs.com/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.Action("LogOnWidget", "Account") %> </div> <div id="menucontainer"> <ul id="menu"> <li><%= Html.ActionLink("Home", "Index", "Home")%></li> <li><%= Html.ActionLink("Profiles", "Index", "Profile")%></li> <li><%= Html.ActionLink("About", "About", "Home")%></li> </ul> </div> </div> <div id="main"> <asp:ContentPlaceHolder ID="MainContent" runat="server" /> <div id="footer"></div> </div> </div></body></html>
在Asp.net mvc中使用母板頁和Web Form中類似,需要定義ContentPlaceHolder,加上使用一些常用的HTML標籤進行布局。 當多個頁面都有同樣的內容的時候,使用母板頁是非常有用的。
2、Partial
Partial類似於Web Form中的使用者控制項。用它來渲染成內容頁,使用Partial最大的好處是這些程式碼片段定義在View頁面,而不是代碼中。下面舉例說明:
渲染partial非常簡單,我們可以在父View中使用RenderPartial和Partial方法,Profiles的代碼如下,在Profiles中使用RenderPartial渲染Profile。
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Profile>>" %><h2>Profiles</h2><table> <tr> <th>Username</th> <th>First name</th> <th>Last name</th> <th>Email</th> </tr> <% foreach (var profile in Model) { %> <% Html.RenderPartial("Profile", profile); %> <% } %></table>
上面的代碼,我將一個profile的List渲染成一個table。每一行定義了一個Partial,用來渲染成一行。即使內容頁不能與其他View分享,在一個View中使用partial可以簡化和減少HTML的標籤數量。RenderPartial方法需要一個partial名字和一個Model參數。根據的partial名字用來搜尋本地的partial檔案,需遵循下面的規則:
1 <Area>\<Controller>\<PartialName>.aspx and .ascx
2 <Area>\Shared\<PartialName>.aspx and .ascx
3 \<Controller>\<PartialName>.aspx and .ascx
4 \Shared\<PartialName>.aspx and .ascx
這些搜尋類似於根據view的name搜尋view,也可以使用<%= Html.Partial("Profile", profile) %> 渲染。Profile檔案即可以是一個ASCX檔案,如果必要也可以是一個aspx的檔案。Profile的代碼如下:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Profile>" %><tr> <td> <%= Html.ActionLink(Model.Username, "Show", new{ username = Model.Username }) %> </td> <td><%= Model.FirstName%></td> <td><%= Model.LastName%></td> <td><%= Model.Email %></td></tr>
我們在View中如下渲染Profiles:
<% Html.RenderPartial("Profiles", Model); %>
渲染效果如下:
3、Child Action
Partial用來顯示已經存在Model的資訊時非常方便的。但是有時候View上顯示的資料來源自其他Model。例如,登入控制項可能會顯示目前使用者的名稱和電子郵件,但該View的主體部分與使用者關係不大。可以使用ViewDataDictionary來傳遞沒聯絡的Model,但是我們可以使用Child Action。對於在View中顯示與主體沒有多大關係的資訊,這裡介紹一下Child Action的使用。下面舉例子說明。
在模板頁中顯示當前的使用者資訊,當使用者登入之後,顯示使用者名稱,郵箱之類的資訊,當使用者沒有登入,給出登入的串連。在模板頁中加入下面代碼:
<div id="logindisplay"> <%= Html.Action("LogOnWidget", "Account") %> </div>
LogOnWidget的代碼如下,ChildActionOnly確保只能通過RenderAction調用此方法。
[ChildActionOnly]public ViewResult LogOnWidget(){ bool isAuthenticated = Request.IsAuthenticated; Profile profile = null; if (isAuthenticated) { var username = HttpContext.User.Identity.Name; profile = _profileRepository.Find(username); if (profile == null) { profile = new Profile(username); _profileRepository.Add(profile); } } return View(new LogOnWidgetModel(isAuthenticated, profile));}
用一個使用者控制項來顯示這個Action的Model的資訊,使用者控制項代碼如下。
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %><%@ Import Namespace="AccountProfile.Controllers"%><% if (Request.IsAuthenticated) {%> Welcome <b><%= Html.Encode(Page.User.Identity.Name) %></b>! [ <%= Html.ActionLink("Log Off", "LogOff", "Account") %> | <%= Html.ActionLink("Profile", "Show", "Profile", new RouteValueDictionary(new { username = Html.Encode(Page.User.Identity.Name) }), null)%> ]<% } else {%> [ <%= Html.ActionLink("Log On", "LogOn", "Account") %> ]<% }%>
總結:本文闡述了三種方式來重構你View的代碼,使用這三種方式可以大量減少View層重複出現的代碼。由於也是最近開始學習asp.net mvc,如果敘述和理解有問題歡迎批評指正。
參考:Asp.net mvc2 in action