天天看點

ASP.NET MVC 中 View 的設計

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 嵌套

比如下面這張圖,(畫的略醜)

ASP.NET MVC 中 View 的設計

那麼我用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()
           

這樣就很完美了。

繼續閱讀