前言
上節我們已經非常清晰並且明確的講了@Html.ActionLink的作用,這一節我們開始講講分部視圖以及孩子Action。
話題
在C#中我們知道繼承的目的是為了代碼的復用,在Web應用程序同樣也是如此,同樣重復的代碼我們需要進行復用。 例如在博客園我們需要渲染每個博客園友的信息。下面我們開始進行演示。我們在創建的項目中的Models文件夾下添加如下一個博客類:
public class Blog { public long Id { get; set; } public string Name { get; set; } public string BlogAddress { get; set; } public string Description { get; set; } }
緊接着我們添加一個博客控制器,如下:
public ActionResult Index() { List<Blog> blogs = new List<Blog>() { new Blog { Id =1, Name ="xpy0928 1",BlogAddress="http://www.cnblogs.com/CreateMyself/", Description ="出生非貧即貴,你我無能為力"}, new Blog { Id =2, Name ="xpy0928 2", BlogAddress="http://www.cnblogs.com/CreateMyself/",Description ="后天若不加以努力趕之超之,又能怪誰呢!"}, new Blog { Id =3, Name ="xpy0928 3",BlogAddress="http://www.cnblogs.com/CreateMyself/", Description ="自己都靠不住不靠譜,又能靠誰呢!" }, new Blog { Id =4, Name ="xpy0928 4", BlogAddress="http://www.cnblogs.com/CreateMyself/",Description ="靠自己!"} }; return View(blogs); }
最后我們在該Action方法對應的視圖Index添加如下代碼:
@model IEnumerable<ASP.NET_MVC_3.Models.Blog> <style type="text/css"> span { color: white; } </style> @foreach (var product in Model) { <div style="background-color:crimson"> ID: <span>@product.Id</span> Name: <span>@product.Name</span> Description: <span>@product.Description</span> Price: <span>@product.Price</span> <hr style="color:white" /> </div> }
下面我們運行程序看看效果:
上面我們簡單的描述了下獲取博客的相關信息,一切都是正常的進行。
那么問題來了,要是每個博客對象有很多屬性那該如何呢?要是我們想在所有頁面都要獲取對象的信息又該如何呢?
難道我們就需要在所有頁面都要寫出所有的對象的屬性嗎?No,MVC已經完全給出了解決方案:利用分部視圖。接下來我們進入分部視圖。
分部視圖
在上面的基礎上,我們來進行改造,我們將視圖Index頁面改寫成如下:
@model IEnumerable<ASP.NET_MVC_3.Models.Blog> <style type="text/css"> span { color: white; } </style> <h2>Blogs</h2> @foreach (var blog in Model) { @Html.Partial("BlogDetails", blog) }
在上述我們利用 @Html.Partial 該方法來請求分部視圖,同樣我們可以利用 Html.RenderPartial 來請求分部視圖,但是這二者處理起來有點區別,當我們在利用 @Html.Partial 渲染分部視圖時我們這樣用:
@foreach (var blog in Model) { @Html.Partial("BlogDetails",blog) }
但是我們利用 Html.RenderPartial 時,如下:
@foreach (var blog in Model) { Html.RenderPartial("BlogDetails",blog) }
此時或報錯,如下:
也就是說在該句末尾必須添加分號(;)。而@Html.Partial有無分號(;)皆可,這個是需要注意的地方,二者還有其他區別。
區別
@Html.Partial返回字符串,而Html.RenderPartial返回void,我們完全可以保存@Html.Partial在一個變量中或者從一個函數中進行返回,但是在Html.RenderPartial不能這樣做,因為其結果在執行期間已經寫到了響應流中 ,由於Html.RenderPartial將結果寫到了響應流中所以Html.RenderPartial的比@Html.Partial執行更加快且高效。因此建議使用Html.RenderPartial。
我們接着在Views文件夾下的Shared下添加BlogDetails視圖,並添加如下代碼:
@model ASP.NET_MVC_3.Models.Blog <div style="background-color: crimson"> ID: <span>@Model.Id</span> Name: <span>@Model.Name</span> BlogAddress: <span>@Model.BlogAddress</span> Description: <span>@Model.Description</span> <hr style="color: white" /> </div>
下面我們繼續來看看結果:
我們利用分部視圖復用了代碼,如果我們想改變對象或者添加屬性我們只需要改變分部視圖即可,利用分部視圖動態進行渲染。上述我們是利用分部視圖進行渲染數據。
那么問題來了,我們上述利用分部視圖是直接請求視圖,要是我們需要根據博客對象傳到后台進行處理過濾數據,我們該如何做呢?請繼續往下看。
ChildAction(孩子Action)
在上述中我們需要將遍歷的博客對象傳到后台進行相應的處理來過濾數據最終跳轉到分部視圖,此時我們需要用到ChildAction特性,我們首先在博客控制器下再創建一個方法,如下:
public ActionResult DisplayBlog(Blog blog) { switch (blog.Id) { case 1: blog.Name = "Child Action Blog 1"; blog.Description = "Child Action Description 1"; break; case 2: blog.Name = "Child Action Blog 2"; blog.Description = "Child Action Description 2"; break; case 3: blog.Name = "Child Action Blog 3"; blog.Description = "Child Action Description 3"; break; case 4: blog.Name = "Child Action Blog 4"; blog.Description = "Child Action Description 4"; break; default: break; } return PartialView("BlogDetails", blog); }
接下來我們在Index頁面需要請求Action方法,如下:
@model IEnumerable<ASP.NET_MVC_3.Models.Blog> <style type="text/css"> span { color: white; } </style> <h2>Blogs</h2> @foreach (var blog in Model) { @Html.Action("Displayblog", blog) }
此時我們運行程序看看,結果如下:
結果正確,但是我們得注意到上述我們沒有用到ChildAction特性,要是有心人直接請求Blog控制器下的DisplayBlog方法呢?我們來看看結果:
沒有得到我們預想的結果,因為我們需要通過Index視圖傳過來的博客對象並對對象作出相應的處理而返回對應的數據,我們直接去請求肯定不會達到我們所預想。由於我們是通過Index視圖傳到DisplayBlog方法,也就是說該方法只是起到了一個間接的作用也就是作為Index的子方法,所以此時我們在該方法上添加如下一句:
[ChildActionOnly] public ActionResult DisplayBlog(Blog blog)
此時我們照樣也得到上述結果,但是當我們直接請求該方法,那么結果該如何呢?我們來看下:
通過[ChildAction]特性修飾后,上述我們是直接請求該DisplayBlog所以會出現如下錯誤,這樣就完全達到了我們的期望,此時若直接請求該方法出現如上錯誤,我們完全可以捕捉到該異常,進行下異常處理並響應不存在該頁面,訪問出錯即可。
結語
本節我們講了分部視圖以及ChildAction的用途,同時也比較兩種分部視圖執行的高效問題,希望對閱讀本篇文章的你有點幫助,我們下節再見。