原文鏈接:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-view
在這一小節,我們將會修改類HelloWorldController來使用視圖模板文件,把為客戶端生成HTML響應的過程封裝起來。
我們將使用在ASP.NET MVC 3中介紹的Razor視圖引擎來創建視圖模板文件。基於Razor的視圖模板使用.cshtml做文件擴展名,它提供了一種優雅的方式來使用c#生成HTML內容。在創建一個視圖模板時Razor可以使我們編寫更少的代碼,使我們的編碼過程快速流暢。
目前Index方法只會返回硬編碼在controller中的字符串。通過下面的代碼可以使Index方法返回一個視圖對象。
public ActionResult Index() { return View(); }
上面的Index方法是用一個視圖模板來生成返回給瀏覽器的HTML響應。Controller方法(又稱action方法),比如Index,通常返回一個ActionResult對象或者從ActionResult派生的對象,而不是像string這樣的簡單類型。
在這個項目里,我們為Index方法添加一個視圖模板,在Index方法內部右鍵單擊,選擇"Add View"。
Add View對話窗口會出現,我們使用默認設置,直接單擊Add按鈕。
這樣做會創建MvcMoview\View\HelloWorld文件夾並且會在該文件夾下創建Index.cshtml文件,你可以在解決方案資源管理器(Solution Explorer)中看到。
下面是新創建的Index.cshtml中的內容
在最后一行加入新代碼,修改后的index.cshtml文件內容如下
@{ ViewBag.Title = "Index"; } <h2>Index</h2> <p>Hello from our View Template!</p>
讓我們啟動程序瀏覽HelloWorld controller(http://localhost:xxxx/HelloWorld),controller中的Index方法並不會做太多的工作,只是單純執行return View()語句,來指明Index方法會使用一個視圖模板來來渲染瀏覽器。因為我們並沒有顯示指出要使用的視圖模板文件的名字,ASP.NET MVC 會默認使用\Views\HelloWorld文件夾下的Index.cshtml視圖文件。下面的截圖顯示了被硬編碼在視圖中的字符串"Hello from our View Template"。
看起來好多了。但是,注意在瀏覽器標題欄里展示的"Index-My ASP.NET M..."和在頁面上方大大的超鏈接"your logo here"。在"your logo here"之后是注冊和登錄的超鏈接,然后是Home,About和Contact頁面的超鏈接,讓我們來做點事情改變這個頁面。
改變Views和布局頁面
首先,來改變頁面頂部的標題"your logo here."。這是每一個頁面都會有的文本。盡管在應用程序中的每一個頁面它都會出現,事實上在項目中只有一個地方實現了它。查看解決方案資源管理器的/Views/Shared文件夾並且打開_Layout.cshtml文件。這個文件被叫做布局頁面(layout page)並且作為其它頁面共享的“外殼”。
布局模板允許我們為網站在一個地方制定HTML容器布局然后將其應用到多個頁面中。找到代碼中的@RederBody()那一行。RenderBody是一個占位符,在所有特定的視圖中會替換掉它。例如,如果你選擇了About超鏈接,Views\Home\About.cshtml視圖會被渲染到RenderBody方法所在的地方。
改變布局模板中網頁頭部的內容(body標簽下的<header>),把"your logo here"改成"MVC Movie"
<div class="float-left"> <p class="site-title">@Html.ActionLink("Mvc Movie", "Index", "Home")</p> </div>
使用下面的標記替換掉title元素中的內容
<title>@ViewBag.Title - Movie App</title>
運行程序,我們會看到現在頁面頭部展示的是"MVC Movie"。點擊About超鏈接,你同樣會看到頭部的"MVC Movie"。我們只需要在布局模板中做一次剛改,就可以影響到所有的頁面。
現在,讓我們來改變一下Index視圖的標題。
打開MvcMovie\VIews\HelloWorld\Index.cshtml文件。有兩個地方需要做修改:第一,出現在瀏覽提標題中的文字;第二,二級標題(<h2>元素).我們把這兩處改的有點不一樣,這樣就能看出來哪一處代碼會影響到程序的哪一部分。
@{ ViewBag.Title = "Movie List"; } <h2>My Movie List</h2> <p>Hello from our View Template!</p>
為了指定展現的HTML標題,上面的代碼為ViewBag(存在於Index.cshtml視圖模板中)對象的Title屬性賦了值。如果你回過頭來看一下布局模板中的代碼,你會發現我們之前修改的布局模板html中的<head>節點下的<title>元素內部使用了ViewBag的這個屬性值。通過使用ViewBag,我們可以輕松地在布局文件和視圖模板之間傳遞參數。
啟動應用程序瀏覽http://localhost:xxxx/HelloWorld。注意一下瀏覽器的標題,主標題和次標題已經改變了(如果你沒有看到改變的話,可能是因為你看到了瀏覽器緩存的內容,按下ctrl+F5強制瀏覽器向服務器請求新頁面)瀏覽器標題由我們在Index.cshtml視圖模板中設置的Viewbag.Title和在布局文件中添加的" – Movie App"共同構造出來。
同樣要注意到Index.cshtml和_Layout.cshtml視圖模板中的內容是怎樣合並到一起生成一個單一的HTML響應發送到瀏覽器的。布局模板使我們修改應用中的多個頁面變得非常容易。
我們僅僅使用的一點點”數據“,是硬編碼的"Hello from out View Template",現在我們的MVC程序有了V和C,但是還沒有M,馬上我們就會介紹如何創建一個數據庫並且從中檢索model數據。
從Controller向View傳遞數據
在我們使用數據庫和討論model之前,先談談關於從controller向view傳遞數據的話題。Controller類在響應傳入的URL請求時被調用。一個controller其實是一個類,這個類由開發者編寫,用來處理傳入的瀏覽器請求,這個類從數據庫中檢索數據並最終決定將什么樣的響應發回瀏覽器。在controller生成HTML響應的時候可以使用視圖模板(View Template)。
Controller負責為視圖模板提供請求的任何數據或者對象。最好的實踐是:視圖模板完全不關心業務邏輯或者並且從不和數據庫直接交互。視圖模板應該僅僅使用到controller傳遞給它的數據。堅持“關注點分離(separation of concerns)”原則有助於我們寫出整潔,可測試和易維護的代碼。
目前,HelloWorldController中的Welcom方法接收name和numTimes參數並且直接將其輸出到瀏覽器。我們現在使用視圖模板替代簡單的字符串。視圖模板將負責動態生成響應,這就意味着我們需要從controller傳遞恰當的數據給它。我們可以通過在controller中把數據存放到視圖模板也可以訪問的ViewBag對象中來做到這一點。
讓我們回到HelloWorldController.cs文件,並且更改Welcom方法,來給ViewBag對象添加Message和NumTimes數據。ViewBag是一個動態類型(c#里的dynamic),也就是說我們可以給它添加任何屬性,在我們給ViewBag添加屬性之前它是沒有任何屬性的。ASP.NET MVC model binding system會自動將url中查詢字符串里的參數映射到方法參數。完整的HelloWorldController.cs文件內容如下:
using System.Web; using System.Web.Mvc; namespace MvcMovie.Controllers { public class HelloWorldController : Controller { // // GET: /HelloWorld/ public ActionResult Index() { return View(); } // // GET: /HelloWorld/Welcome/ public ActionResult Welcome(string name, int numTimes = 1) { ViewBag.Message = "Hello " + name; ViewBag.NumTimes = numTimes; return View(); } } }
現在包含了數據的ViewBag會自動傳遞給View。
接下來,我們需要一個Welcom視圖模板,我們需要先編譯一下項目。選擇“Build”菜單里的"Build MvcMovie"選項。
在Welcom方法內部右鍵單擊選擇"Add View"。
會彈出如下的Add View對話框
單擊Add,在Welcom.cshtml文件里的<h2>元素下面添加代碼。創建一個循環來按照用戶的要求輸出"Hello",完整的Welcom.cshtml文件內容如下
@{ ViewBag.Title = "Welcome"; } <h2>Welcome</h2> <ul> @for(int i=0;i<ViewBag.NumTimes;i++) { <li>@ViewBag.Message</li> } </ul>
運行應用程序訪問如下的URL:
http://localhost:xx/HelloWorld/Welcome?name=Scott&numtimes=4
URL里攜帶的數據通過model binder會傳遞給controller。controller將數據打包到ViewBag對象然后傳遞給View。View將數據展示為html。
在上面的例子中,我們使用ViewBag對象來從controller傳遞數據給view。在接下來的文章里,我們會使用view model來傳遞數據。使用view model來傳遞數據比ViewBag對象更好,更多的內容可以參考Dynamic V Strongly Typed Views。