文章目錄
- 先說分頁欄吧
- 接下來Sidebar
- 看看緩衝是否有效
在上一篇文章中,我建立了一個Blog項目,今天我打算繼續折騰一下這個項目。
如果你還不瞭解ASP.NET MVC3的布局,你可以先看看這篇文章,應該會對你有所協助的。
主要講一下自己對ASP.NET MVC3中的局部視圖以及緩衝的認識,不多說先上幾幅圖吧。
第一幅圖是部落格首頁分頁欄的,第二幅圖就是部落格的Sidebar了。我分別用 ASP.NET MVC3 提供的兩種局部視圖實現。 有人可能會問,為什麼要用兩種不同的方法,你這不是裝13嗎? 。。。。我想我只能“呵呵”以對了,使用什麼方法當然是根據需求而選的。
第三幅圖是完成後的頁面結構
先說分頁欄吧
要做成上面的導覽列,我們需要哪些資料呢? 1. 當前頁碼 2. 每頁顯示多少文章 3. 資料庫裡有多少文章
OK,既然只要需要這些,那我們就在HomeController的IndexAction裡通過ViewBag提供給他吧。
public class HomeController : Controller{ BlogDB db = new BlogDB(); // GET: /Home/page/5 public ActionResult Index(int page = 1) { int countPerPage=10; var posts = db.Posts.Include("Category") .Include("Tags").Include("Comments") .OrderByDescending(p=>p.CreateTime) .Skip((page - 1) * countPerPage) .Take(10); ViewBag.CurrentPage = page; ViewBag.CountPerPage = countPerPage; ViewBag.PostsCount = posts.Count(); return View(posts); }}
資料有了,就讓我們開始建立局部視圖吧。
開啟右擊View檔案夾中的Share檔案夾,選擇添加視圖。我這裡將他命名為_Pagination,注意
小技巧 : 在 ASP.NET MVC3 中,如果一個視圖以"_"開頭命名的話,外部是不能單獨訪問他的,他只能作為局部視圖嵌套在其他視圖中。
開啟剛剛建立好的視圖,添加如下代碼
@{ int pageCount = ViewBag.PostsCount / ViewBag.CountPerPage + 1; int currentPage = ViewBag.CurrentPage;}<div class="pagination"> <span class="first_page"><a href="/">First</a></span> @for (var i = 1; i <= pageCount; i++) { if (i == currentPage) { <span class="page_num current_page"> <a href="/page/@i">@i</a> </span> } else { <span class="page_num "> <a href="/page/@i">@i</a> </span> } } @if (currentPage == pageCount) { <span class="next_page"><a href="/page/@pageCount">Next</a></span> } else { <span class="next_page"><a href="/page/@(currentPage+1)">Next</a></span> }</div>
我們在Home Index View中調用這個局部視圖
@model IEnumerable<Blog.Models.Post>@{ ViewBag.Title = "NinoFocus | Notepad";}<div id="main">@Html.Partial("_PostList", Model)<!-- 看這裡,看這裡,我們通過下面的語句調用他 -->@Html.Partial("_Pagination")</div><!--#END main-->
恩,好了,分頁欄就算完成了。
接下來Sidebar
Sidebar 和 分頁欄 不同,因為分頁欄只在首頁顯示,所有首頁可以提供資料給他。而Sidebar確實無論哪個頁面都要顯示的,所以他必須要自己給自己提供資料。
好,看到這裡可能有人會想,那還不和上面的一樣嗎?我在頁面上寫一些伺服器端的代碼,提供資料會死啊?
就像這樣
<li> <h4 class="h4"> <span>一些酷酷的 <strong>網站</strong></span></h4> <ul> @foreach (var link in new Blog.Models.BlogDB().FriendLinks) { <li><a href="@link.URL" title="@link.Name"> <strong>@link.Name</strong></a> - @link.Description </li> } </ul></li>
會死嗎?當然不會啦,這也是一種解決方案啊(雖然我不推薦在)。但是,我想想又覺得不妥啊,Sidebar的資料更新頻率很低的啊,這樣每次重新整理頁面或者瀏覽其他頁面都要重新請求資料庫,這是不是不妥啊?
為了讓他變得妥妥的,同時也充分的壓榨一下ASP.NET MVC的特性。我還是決定使用ChildAction了。
添加一個ChildActionController,主要負責一些局部視圖的工作(其實就是提供資料用的)。下面我以Sidebar中的友情連結為例,說一下Action的代碼。
[ChildActionOnly][OutputCache(Duration = 3600)]public PartialViewResult SidebarFriendLinks(){ var links = db.FriendLinks; return PartialView(links);}
[ChildActionOnly] 屬性說明這個Action只能內部調用,不能被外部單獨訪問。
[OutputCache] 啟用緩衝,Duration欄位是緩衝時間,以秒為單位,這裡我設為1小時。
為了您的健康Action的傳回值類型還是用 PartialViewResult 不要用平時常用的 ActionResult ,不然會死很多腦細胞的,我昨晚就被這個搞死。 ASP.NET MVC 遵循DRY(Don't repeat yourself)原則,如果你沒有為ActionResult的View指定模板頁的話,他會自動的給你加上預設的模板頁。預設的模板頁可以在_ViewStart.cshtml檔案中指出
@{ Layout = "~/Views/Shared/_Layout.cshtml";}
如果你看了我上面推薦的關於ASP.NET MVC3布局的文章,你會知道這是好東西的。
讓我們類比一下頁面的調用,我們在使用了模板頁的頁面中調用SidebarFriendlinks,然後SidebarFriendLinks有調用了模板,然後模板頁調用了SidebarFriendLinks,然後。。。。然後你就悲劇了啊。
如果您一定要使用ActionResult作為傳回值的話,那就給局部頁面加上下面的語句吧
@{ Layout = null;}
所以為了健康,還是使用PartialViewResult吧。
恩,就此打住,讓我們繼續吧。右擊SidebarFriendLinks選擇添加視圖。
讓我們開啟SidebarFriendLinks.cshtml檔案,修改一下@model 後的語句,然後添加頁面代碼
@model IEnumerable<Blog.Models.FriendLink><li> <h4 class="h4"> <span>一些酷酷的 <strong>網站</strong></span></h4> <ul> @foreach (var link in Model) { <li> <a href="@link.URL" title="@link.Name"> <strong>@link.Name</strong> </a> - @link.Description </li> } </ul></li>
然後在_Sidebar.cshtml中調用他
<div class="sidebar"> <ul> @Html.Action("SidebarTags","ChildAction") @Html.Action("SidebarArchive","ChildAction") @Html.Action("SidebarFriendLinks","ChildAction") </ul></div><div class="clear"></div><!-- END sidebar -->
這樣寫的 sidebar 以後我是不是就可以通過設定檔來控制裡面的內容了呢,嘎嘎噶!!!
最後奉上_Layout.cshtml的代碼,只求大家對這個部落格的頁面結構有個更加清晰的瞭解
<!DOCTYPE html><html><head> <title>@ViewBag.Title</title> <link href="Content/Site.css" rel="stylesheet" type="text/css" /></head><body class="homepage"> <div id="container"> @Html.Partial("_Header") @Html.Partial("_Navigation") <div id="body"> <div id="content"> @RenderBody() </div> @Html.Partial("_Sidebar") </div> </div> @Html.Partial("_Footer") <!-- Script --> @RenderSection("footerScript",false) <!-- End Script--></body></html>
@RenderBody() 就是其他頁面填充內容的地方。
@RenderSection("footerScript",false) 預留的空間,第一個參數表示名稱,第二個參數如果是false的話,表示不是每個頁面都必須往裡面新增內容;如果是true的話,就表示使用了這個模板的頁面都必須往裡面填寫內容。
在頁面上,可以這樣調用
@section footerScript{ ...javascript here}
看看緩衝是否有效
開啟SQL Server Profiler來監視一下資料庫請求。
1. 未開啟緩衝時
在沒有開啟緩衝的情況下,我每次重新整理部落格首頁,會有5條(我sidebar裡放了3個局部頁面)資料庫請求
為什麼使用EF時同樣的SQL語句會被請求兩次?求解!!! 我這裡暫且算他一次先。
2. 開啟緩衝時
現在我啟用sidebar的緩衝,來看看重新整理頁面的資料庫請求次數
請求次數從5次,變成2次了。說明緩衝成功開啟了。呵呵,有點爽爽的。
於是貪得無厭的我又把首頁也加了緩衝
//// GET: /Home/page/5[OutputCache(Duration=60*5)]public ActionResult Index(int page = 1)
現在重新整理頁面看看
沒有資料庫連接請求了,啦啦啦啦。
貌似部落格園的首頁也加了緩衝吧,好像一兩分鐘的樣子。
標籤: ASP.NET MVC