1. 前言
感覺有好長時間沒有接觸
View
了,周末閑來無事,翻翻書桌上的書來回顧回顧
ASP.NET MVC
中
View
的相關内容。
2. View概述
View
通過應用程式在
Action
中傳回
ViewResult
或
PartialViewResult
,在運作階段内部調用
ExecuteResult
方法而産生模版轉換(
transforamtion
),将運作階段運算後産生的Model 經由模版引擎(
template engine
) 進行轉換,進而生成HTML頁面代碼,輸出到浏覽器。
//_ViewStart.cshtml
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
_ViewStart.cshtml
的預設
Layout
行為并不适用于
Partial View
部分試圖,
Partial View
不會引用這項指定。
2.1 Layout 的結構
下面是Layout 的示例代碼:
<!--Layout 示例-->
<html>
<head>
<titile>@ViewBag.Title</titile>
@RenderSection("head")
</head>
<body>
<div class ="header">
<!--這裡放header 的内容-->
</div>
<div class ="main">
<div class = "aside">
<!--這裡放側邊欄拉或者菜單等等-->
@RenderSection("sideBar", required:false)
</div>
<div class = "content">
@RenderBody();
</div>
</div>
<div class= "footer">
<!--這裡放頁面底部的内容-->
</div>
@RenderSection("Script",required:false)
</body>
</html>
2.2 RenderSection
@RenderSection
具有一個必要參數作為區域名稱,并且有一個可選參數
required
, 省略
required
參數或者設定
required:true
用來指定套用這份
Layout
的
View
是否必須滿足這個區域,如果沒有提供該區域,會報錯。
<!--@RenderSection示例-->
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
@section head{
<meta name="description" content = "This is a test View By Robert."/>
}
@section sideBar{
<h2>
Hello, Are you Ok?
</h2>
<ul>
<li>
<a href ="http://www.cnblogs.com">cnblogs</a>
</li>
<li>
<a href = "http://q.cnblogs.com">q.cnblogs.com</a>
</li>
</ul>
}
hahahhaha
2.3 Layout 與View 的執行順序
在執行順序上,
View
會被優先執行,然後被
View
引用的
Layout
執行,這一點經常會被誤解為相反的情況。例如在程式中以
ViewBag
、
ViewData
在
View
與
Layout
之間進行變量的傳遞,就會有執行順序的問題需要考慮,是以一開始需要特别留意。
3 View 擷取資料的方法
下面用一個表來展現幾種傳遞資料的方式:
方式 | 優點 | 缺點 |
---|---|---|
Model | 強類型,得以在編譯期間進行類型檢查 | 當以string 類型作為ViewModel 時會有一點小麻煩 |
ViewData | 不需要建立ViewModel 類即可進行傳遞資料 | 弱類型,無編譯期間類型檢查 |
ViewBag | ||
TempData | 不需要建立ViewModel 類即可進行傳遞資料,可以跨Action傳遞 |
Model
類型就不多說了,接下來講一下
ViewBag
,
ViewData
以及
TempData
3.1 ViewData 和ViewBag
ViewData
是
Controller
執行個體中的屬性,類型為
ViewDataDictionary
ViewDataDictionary
實作了
IDictionary<string,object>
, 将
Dictionary
中的
TValue
泛型參數聲明為
object
,故可以放置任意類型資料。
//指派
ViewData["Now"] = DateTime.Now;
//使用
@ViewData["Now"]
//讀取
var dateTime = (DateTime)ViewData["Now"];
ViewBag
Controller
dynamic
, 與
ViewData
性質完全相同,隻是使用的機制稍有不同。
//指派
ViewBag.Now = DateTime.Now;
//使用
@ViewBag.Now
//讀取
var dateTime = (DateTime) ViewBag.Now;
若以“
@ViewBag.自定義屬性
” 或 “
@ViewData["自定義屬性"]
”的方式在頁面中呈現内容,是不需要考慮類型轉換的。由于都會以
ToString
方法強制為字元串輸出,是以在隻是輸出的簡單情況下不必編寫複雜的類型轉換程式代碼。
3.2 TempData
TempData
Controller
TempDataDictionary
TempDataDictionary
IDictionary<string,object>
。
各種特性讓TempData 行為看起來與
ViewData
ViewBag
相似,但實際上存放在
TempData
的資料隻要經過一次讀取就會消失在容器中,另一個特性是如果資料隻存不取,那麼這份資料的預設有效期與
ASP.NET Session
一樣長,未經調整的
Session
有效期為20分鐘。在
ASP.NET MVC
内部的原因是
TempData
通過内部的
SessionStateTempDataProvider
實作将暫存資料放置于
Session
中。
4 Layout 嵌套
比如下面這張圖,(畫的略醜)

那麼我用Layout 的代碼如何設計呢?如下所示:
<!--_Layout.cshtml-->
<html>
<head>
<link rel = "stylesheet" href ="~/Content/test.min.css"/>
@RenderSection("head",required:false)
</head>
<body>
<div class = "header">
<!-- 放Logo 啥的-->
</div>
<div class = "content">
@RenderBody();
</div>
<div class = "footer">
<!--頁面底部-->
</div>
<script src = "~/Scirpts/test.min.js"></script>
@RenderSection("scripts",required:false)
</body>
</html>
接下來是_AsideLayout.cshtml
<!--_AsideLayout.cshtml-->
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
@section head
{
<!-- 這裡放需要在head 中額外加入的内容-->
<!--可以繼續保留 否則head section 到此為止-->
@RenderSection("head",required:false)
}
@section scipts{
<!-- 這裡和上面一樣,繼續保留 供其他調用使用-->
@RenderSection("scripts",required:false)
}
<div class = "aside">
@RenderSection("sideBar", required:false)
</div>
@RenderBody()
這樣就很完美了。