摘要:ASP.NET MVC3: 通過Razor實現佈局
原文發表位置:ASP.NET MVC 3: Layouts with Razor
原文發表時間:October 22, 2010 3:05 PM
註:本文使用的排版 (layout) 一詞指的是網頁的排版,MVC 使用的 Rendering Engine (不論是 Razor 或是 aspx) 在 View 中所做的都是網頁排版,有些文章會將 Layout 譯為排版。
透過 Razor 使用排版
在我上一篇部落格中,我Demo了一個簡單的例子來顯示一列商品目錄的商品URL:
下面用一個簡單的ProductsController實現上面的商品URL列表。它從資料庫傳回一列商品種類,然後傳到 View 檔案,以在瀏覽器以合適的HTML回應顯示出來。
下面顯示Index.cshtml View 檔案(用Razor實作)
上面的 View 檔案沒有使用排版頁面——這意味著我們往站點添加新的URLs和頁面的時候我們會在不同的地方重複我們的核心網站排版。使用排版可以讓我們避免這種重覆工作,以後管理我們的網站設計更加容易。讓我們現在更新我們的範例來使用一個吧。
重構以使用排版
Razor使重構現有頁面以使用排版變得簡單。 讓我們用上面的簡單範例做一下吧。 我們的第一步是往項目的 \Views\Shared(這是通用 View、模板所放置的地方)下添加一個「SiteLayout.cshtml」檔案:
SiteLayout.cshtml
我們將用SiteLayout.cshtml檔案來定義我們網站的通用內容, 可能看起來像下面這樣:
上面檔案需要注意:
- 檔案頂端不需要有一個@inherits指令了。你想要的話也可以選擇加上一個(比如:如果你希望有一個客制的基底類別),但是這不是必需的。這樣就能讓檔案美觀而乾淨, 而且也方便程式設計師之外的人處理檔案, 遇到他們不理解的概念也不會覺得疑惑。
- 我們在上面的排版檔案中調用@RenderBody()方法,
- 我們在<head>部分的<title>元素內輸出「View.Title」屬性。我還將討論一下這是怎麼使用的。
現在我們有了一個通用的排版模板來保持我們網站任意頁面的外觀一致性。
Index.cshtml
我們下面根據我們剛才建立的SiteLayout.cshtml檔案來更新我們的Index.cshtml View。下面是它可能的樣子的首次截圖:
關於上面的檔案需要注意:
- 我們不需要將我們的主體內容包裝在一個標記或元素中——Razor將預設自動將Index.cshtml中的內容視為排版頁面的主體部分。如果我們的排版有幾個可更換的區域,我們能選擇性地定義「name sections」。但是Razor讓90%的情況(你只需要有一個主體部分就可以了)超級乾淨而簡練。
- 上面我們程式化設置了Index.cshtml頁面中的View.Title的值。我們的Index.cshtml檔案中的程式碼會比SiteLayout.cshtml中的程式碼先執行——這樣我們就能編寫 View 程式碼配置需要被顯示到網頁中的值。物件配置頁面的標題,和為搜尋引擎最佳化內的<head>設置<meta>元素這樣的事情,上面功能尤其有用。
- 剛才我們在Index.cshtml頁面內程式化設置所用的排版模板。它也可以通過設置視圖上的排版屬性來實現(注意:在第一個預覽版中,這個屬性被稱為「LayoutPage」——我們在ASP.NET MVC 3 Beta版中將其更名為「Layout」)。我將簡單地介紹設置這個屬性的幾個替代方法。
現在當我們在網站內請求 /Product URL的時候,將得到傳回如下HTML:
注意上面是怎樣傳回一個SiteLayout.cshtml和Index.cshtml的合併HTML內容的。頂端的「Product categories」標題根據視圖正確設置,我們的動態目錄列表顯示在正確的位置。
用 _ViewStart 保持「乾燥」(DRY)
現在我們在Index.cshtml檔案的頂端透過程式化設置所要用的排版檔案。對包含一些專門針對 View 的邏輯的情況還好,因為排版檔案會隨著特定 View 的不同而不同。但是這樣設置的話會最終導致大部分網頁應用程式的程式碼贅餘和重覆——要不就所有的 View 都使用同樣的排版,要不這樣:如果他們有不同的排版(比如:對 Moblie Device 或本地化網站),選擇使用排版的邏輯在所有 View 中通用。
好消息是Razor包括一個能讓我們不需要在每個視圖中明確設置排版的新功能——而是讓我們能一次性定義網站內所有 View 的排版邏輯,從而讓我們的 View 更乾淨,也更容易維護(確保我們堅持DRY原則:不要重複你自己):
自 ASP.NET MVC 3 BETA 開始, 你現在能在專案的 \Views 資料夾下添加一個 _ViewStart.cshtml(或 VB 的 _ViewStart.vbhtml)的檔案:
_ViewStart 檔案可以被用來定義想要在每次 View 呈現開始的時候執行的通用 View 程式碼。比如,我們能在在我們的 _ViewStart.cshtml 檔案中寫下面這樣的程式碼來程式化設置每個 View 的預設排版屬性為 SiteLayout.cshtml 檔案:
因為這段程式碼在每個 View 開始的時候執行,我們不需要在任何單個 View 檔案中顯式設置排版(除非我們想要覆蓋上面的預設值)。
重要: 因為 _ViewStart.cshtml 允許我們編寫程式碼,所以我們能有選擇地讓我們的排版選擇邏輯比基本的屬性設置更豐富。比如:我們能根據訪問網站的設備的不同來使用不同的排版模板——有針對手機或tablet等這些設備的最佳化排版,針對PCs/筆記型電腦的桌面最佳化排版。或者如果我們建立一個被不同的用戶使用的CMS系統或通用共享應用,我們能根據訪問網站的客戶(或角色)的不同而選擇不同的排版。
這大大提高了用戶介面的靈活度。允許你更容易地一次性編寫 View 邏輯,避免在不同的地方重覆使用它。
注意:你也能在一個控制器或操作篩選器重新指定排版。這樣如果你更願意保留排版邏輯在那裡,你也能那樣做。
完成的範例
下面是我們一直在建立的簡單應用程式的截圖:
下面是ProductsControlles,它實現/Product URL並從資料庫傳回目錄並將它們傳到 View 模板顯示出來:
這裡是我們用來顯示/Products回應的Index.cshtml View:
這裡是用來在網站內實現統一外觀的SiteLayout.cshtml排版檔案:
這裡是指定我們所有 View 都預設使用 SiteLayout.cshtml 檔案的 _ViewStart.cshtml 檔案:
這裡是/Products URL所生成的HTML:
既然我們現在的網站上有了一個通用排版檔案,我們能在應用程式中構建更多功能,控制器和 View ——從而獲得一個連貫又容易維護的網站用戶介面體驗。
更多高級內容
人們經常問兩個常見問題:
1) 我能使用內嵌的排版檔案嗎?
2) 在一個排版檔案中,我們有多個非連續的可替換區域嗎?——這樣我就能在幾處不同的地方填充我自己的 View 檔案。
這兩個問題的答案都是肯定的!我以後會寫一些展示如何實現的範例的文章。
總結
像我之前提到的,我們發佈 ASP.NET MVC 3和 Razor 所堅持的一個主旨是讓你寫的程式碼更乾淨更簡潔。我們認為這個發佈版帶來的新排版功能非常有助於方便 View 檔案的讀寫。
希望對您有所幫助。
Scott
附:除了發表部落格之外,我還用Twitter進行快速更新和分享連結。請關注我:twitter.com/scottgu