我的MVC之旅(3)--------MVC Music Store 第三篇 Views and ViewModels [翻译]
?前言
? 有網友說不要浪費時間了趕緊干點正事,也有人覺得還不錯;我個人覺得看懂是一回事,但是能夠寫出來分享是另一回事,這樣記憶深刻有助于加深自己的理解,而且可以幫助有些和我一樣的初學者,遇到的問題,怎么解決等等.
好了,下面開始正題.上周做完第二篇控制器之后,接下來就是第三篇 視圖和模型了,源文章鏈接:http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-3
概述
本章通過簡單的幾個示例,介紹視圖的使用方法以及控制器和視圖之間的數據傳遞方法,簡單而且直觀,并且簡單介紹了生成頁面鏈接的方法.
內容
?先來回顧一下:我們之前已經使用控制器返回String 類型的字符,這很好的讓我們了解了控制器的工作原理,但是這不是真正的web應用程序.
我們想要一個更簡單的方式返回HTML內容到瀏覽器--模版文件可以輕松地自定義HTML內容并發回瀏覽器,這就是視圖.
1.添加第一個視圖:
要應用視圖,首先要改變HomeController 控制器的 Index方法的返回值為ActionResult,并且我們讓他返回一個View();代碼如下:
1?? 2?????????//3?????????//?GET:?/Home/
4?
5?????????public?ActionResult?Index()
6?????????{
7?????????????return?View();
8?????????}
上面的代碼表示,我們想使用視圖得到一個結果返回.
我們現在添加一個視圖 到我們的項目里面,光標定位到Index()方法,右鍵單擊選擇添加視圖:
?
? 添加視圖對話框允許我們快速方便地生成視圖文件,默認情況下,添加視圖對話框已經為我們光標定位的控制器方法添加好了名稱,我們不需要修改什么,直接點擊確定,就會添加一個試圖文件到工程目錄:Views/Home/Index.cshtml.
視圖文件的名字和目錄非常重要,使用Mvc默認的命名規則,目錄/View/Home 對應HomeController,文件Index.cshtml對應控制器方法:Index().?使用這種命名規則,我們不用在Index()方法中顯示指定視圖文件,而是直接 ?return View().就像上面的HomeController.Index(),它將會自動引用View/Home/Index.cshtml.
添加完視圖之后,默認會打開該視圖文件,默認代碼如下:
1?@{ 2?????ViewBag.Title?=?"Index";3?}
4?
5?<h2>Index</h2>
該視圖文件使用?Razor 語法?,這比Asp.net Web Forms 中的 Web Forms視圖引擎和上一版本的Asp.net mvc 更簡潔.當然 WebForms視圖引擎在Asp.net 3.0中仍然可用,但是很多開發者覺得Razor更加適用于Asp.net Mvc 開發.
? 前三行代碼設置頁面標題ViewBag.Title.我們等一下將看看它是怎么工作的,現在我們改一下頁面的代碼:
1?@{ 2?????ViewBag.Title?=?"Index";3?}
4?
5?<h2>This?is?the?Home?Page</h2>
接下來運行程序看一下主頁,會看到我們已經更新的文本:
現在,我們已經為HomeController.Index添加了視圖Index.cshtml,并且運行了出來。下面我們即將看一下Mvc給我們提供的統一網站部局文件.
2.使用統一布局文件
很多網站的網頁有一些全站公用的東西:導航,頁腳,LOGO,CSS文件等.Razor 讓我們很輕松地管理這些東西,使用_Layout.cshtml,工程已經為我們建立此文件,位于:/Views/Shared/_Layout.cshtml.
我們看一下布局文件:
?1?<!DOCTYPE?html> ?2?<html>?3?<head>
?4?????<meta?charset="utf-8"?/>
?5?????<title>@ViewBag.Title</title>
?6?????<link?href="@Url.Content("~/Content/Site.css")"?rel="stylesheet"?type="text/css"?/>
?7?????<script?src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")"?type="text/javascript"></script>
?8?????<script?src="@Url.Content("~/Scripts/modernizr-2.5.3.js")"?type="text/javascript"></script>
?9?</head>
10?
11?<body>
12?????@RenderBody()
13?</body>
14?</html>
? 很簡單,僅包含一些CSS和常規腳本.我們的視圖文件將會通過 @RenderBody()命令來展示,其他的公共內容都可以在這里添加,我們想讓我們的MuvMusicStore用一個公共的頁眉,上面包含首頁鏈接和商店鏈接,所以,我們在@RenderBody()命令上面添加一些代碼(黃色高亮部分),個人覺得這里和母版差不多.
添加完之后,先不要運行?
?1?<!DOCTYPE?html> ?2?<html>?3?<head>
?4?????<meta?charset="utf-8"?/>
?5?????<title>@ViewBag.Title</title>
?6?????<link?href="@Url.Content("~/Content/Site.css")"?rel="stylesheet"?type="text/css"?/>
?7?????<script?src="@Url.Content("~/Scripts/jquery-1.7.1.min.js")"?type="text/javascript"></script>
?8?????<script?src="@Url.Content("~/Scripts/modernizr-2.5.3.js")"?type="text/javascript"></script>
?9?</head>
10?
11?<body>
12?????<div?id="header">
13?????????<h1>ASP.NET?MVC?MUSIC?STORE</h1>
14?????????<ul?id="navlist">
15?????????????<li?class="first"><a?href="/"
16?????????????????id="current">Home</a></li>
17?????????????<li><a
18?????????????????href="/Store/">Store</a></li>
19?????????</ul>
20?????</div>
21?????@RenderBody()
22?</body>
23?</html>
空項目模版進包含一些基本的css用于顯示驗證消息,本項目設計師添加了一些常用的Css和一些圖片來控制我們的應用程序的外觀,我們需要把這些文件同時添加進項目里(可以去這里下載)
下載完成解壓之后,打開相關文件包,選擇我們需要的文件添加到項目里:
?現在,我們重新生成并刷新首頁:
?
是不是很熟悉:這就是母版.
? 簡單回顧一下:
- HomeCongroller.Index引用并展示/Views/Home/Index.cshtml ,盡管我們并沒有顯示指定視圖文件地址而只是使用return View();但是因為我們使用Mvc默認命名規則,所以,這樣并不會導致找不到文件.
- 首頁通過視圖文件展示一個簡單的歡迎信息.
- 使用統一布局文件,讓歡迎信息顯示于全局統一風格的頁面中。
?
3.使用模型傳遞數據到視圖
只有html代碼的靜態頁面不能滿足我們的應用程序要求,我們需要的是一個能夠和用戶溝通的動態網站,我們需要把數據從控制器傳遞到視圖文件.
在Model-view-controller模式里,Model表示?應用程序中的數據.Model一般對應數據庫中的表,但這不是必須的.
返回一個ActionResult的控制器可以傳遞一個Model到視圖,控制器可以打包所有需要的數據,生成輸出并傳遞到目標視圖文件用來得到Html輸出給瀏覽器,這很簡單,讓我們看看怎么做.
首先我們需要建立一些Model類:Genres(流派),Albums(相冊).右擊/Models/文件夾,選擇添加/類,命名為:Genre.cs,確定之后編輯器會打開Genre.cs文件,我們添加公共屬性Name
?2?using?System;?3?using?System.Collections.Generic;
?4?using?System.Linq;
?5?using?System.Web;
?6?
?7?namespace?MvcMusicStore.Models
?8?{
?9?????public?class?Genre
10?????{
11?????????public?string?Name?{?get;?set;?}
12?????}
13?}?
? 相同步驟創建Album.cs,有一個Title屬性和 ?Genre屬性:
?2?using?System;?3?using?System.Collections.Generic;
?4?using?System.Linq;
?5?using?System.Web;
?6?
?7?namespace?MvcMusicStore.Models
?8?{
?9?????public?class?Album
10?????{
11?????????public?string?Title?{?get;?set;?}
12?????????public?Genre?Genre?{?get;?set;?}
13?????}
14?}
現在,我們可以修改StoreController 使用視圖從模型顯示動態信息,我們給Albums一個和Request ID相同的名字(演示起見).
首先:打開StoreController.cs,修改Details 方法,讓它顯示一個相冊的信息,引入MuvMusicStore.Models命名空間以便于使用相關模型類,修改Detail的返回值類型:string to ActionResult,修改方法邏輯:返回一個Album對象給View(稍后我們會講如何從數據庫檢索數據),?但是現在我們將使用“模擬數據”.
給Details添加視圖文件,不過這個步驟要復雜一點點,在添加視圖對話框里我們要勾選“創建強類型視圖” 然后在下面選擇?Album (MvcMusicStore.Models),如果下拉框里面沒有選項,請重新生成項目后重試,支持模版就用Empty ,勾選 引用腳本庫,點擊確定我們會看到生成的視圖文件如下:
2?@model?MvcMusicStore.Models.Album3?
4?@{
5?????ViewBag.Title?=?"Details";
6?}
7?
8?<h2>Details</h2>
比我們剛才添加的HomeController.Index的視圖多了第一行:它表明這個視圖強制關聯到 Album class,Razor引擎會識別傳進來的Album對象,所以我們可以在視圖編輯器中輕松訪問 模型屬性,并且寫代碼時候能夠自動感應.
更新<h2>標簽內容:
?2?@model?MvcMusicStore.Models.Album?3?
?4?@{
?5?????ViewBag.Title?=?"Details";
?6?}
?7?
?8<h2>Album:?@Model.Title</h2>
?9?
當你輸入 @Model 之后,智能感知便會出現所有的成員.
現在我們重新生成之后訪問 ??/Store/Details/5?:
現在我們給Browse方法一個相應的修改:
更新StroeController.Browse方法:
2?public?ActionResult?Browse(string?genre)3?????????{
4?????????????var?genreModel?=?new?Genre?{?Name?=?genre?};
5?????????????return?View(genreModel);
6?????????}
給Browse 添加視圖,強類型關聯到Genre
更新Browse.cshtml代碼:
2?@model?MvcMusicStore.Models.Genre3?@{
4?????ViewBag.Title?=?"Browse";
5?}
6?<h2>Browsing?Genre:?@Model.Name</h2>
重新生成項目并訪問??/Store/Browse?Genre=Disco:
? 最后,我們給StoreController.Index一個稍微復雜的邏輯和視圖來展示一個流派列表,我們使用一個Genres列表,而不是單個對象:
StoreController.Index代碼:
?3?????????//?GET:?/Store/?4?????????public?ActionResult?Index()
?5?????????{
?6?????????????var?genres?=?new?List<Genre>
?7?????????????{
?8?????????????????new?Genre?{?Name?=?"Disco"},
?9?????????????????new?Genre?{?Name?=?"Jazz"},
10?????????????????new?Genre?{?Name?=?"Rock"}
11?????????????};
12?????????????return?View(genres);
13?????????}
給Index添加視圖強類型管理到Genre,打開視圖文件Models/Store/Index.cshtml,把第一行的接收參數生命更新:
2?@*注釋*@3?@*@model?MvcMusicStore.Models.Genre??*@
4?@model?IEnumerable<MvcMusicStore.Models.Genre>
@**@表示注釋代碼
第四行代碼表示我們將接受多個Genre對象;
我們使用?IEnumerable<Genre>而不是 ?List<Genre>,是因為IEnumerable更為通用,我們可以傳遞任意實現IEnumerable接口的參數類型.
下面我們將遍歷Genre對象:
?2?@*@model?MvcMusicStore.Models.Genre??*@?3?@model?IEnumerable<MvcMusicStore.Models.Genre>
?4?@{
?5?????ViewBag.Title?=?"Store";
?6?}
?7?<h3>Browse?Genres</h3>
?8?<p>
?9?????Select?from?@Model.Count()
10?????genres:
11?</p>
12?<ul>
13?????@foreach?(var?genre?in?Model)
14?????{
15?????????<li>@genre.Name</li>
16?????}
17?</ul>
? 任然有非常強悍的智能感知:比如輸入@Model會出來所有支持的成員;
循環內部,每個 var生命的genre 也可以智能感知所有的成員;
現在我們已經可以循環傳入對象列表,并輸出對象總數以及每個對象的信息,以后我們會生成編輯、查看詳細信息和刪除操作到每一項,現在我們先來看看簡單列表:
重新生成項目,訪問??/Store:
?
? 4.添加站內鏈接
剛才的 /Store頁面展示了一組Genre對象的Name屬性作為普通文本,我們給他們加上鏈接,通過點擊訪問相關的詳細信息/Store/Browse,當我們點擊 "Disco",能夠跳轉到/Store/Browse?genre=Disco,我們更新/Views/Store/Index.cshtml的代碼:
2?<ul>3?????@foreach?(var?genre?in?Model)
4?????{
5?????????<li><a?href="/Store/Browse?genre=@genre.Name">@genre.Name</a></li>
6?????}
7?</ul>
? 這樣可以實現,但是不是很好的方式,比如我們要更新Browse為BrowseDetail,那就需要檢索整個項目來查找需要更新的地方.
另一個實現方式就是利用 HTML Helper 方法.Asp.net Mvc包含HTML Helper方法,在View編輯器中,我們可以使用它來完成相關的任務. Html.ActionLink()是一個特別有用的方法,使用它創建鏈接,維護路徑,還是確保URL編碼都比較簡單,
? Html.ActionLink()有幾個重載允許我們傳入需要的各種參數, 在示例中我們僅需要提供鏈接文本和目標Action,比如我們可以在Store Details 頁面點擊"Go to Store Index" 連接到"/Store"頁面,用法如下:
2?@Html.ActionLink("Goto?the?Store?Index",?"Index")? 鏈接到Browse頁面需要一個參數,所以我們需要另外一個重載,它將支持三個參數:
?
- 鏈接文本
- 控制器名稱
- 參數 包括參數名和參數值
?
? 下面看一下代碼:
?2?@*@model?MvcMusicStore.Models.Genre??*@?3?@model?IEnumerable<MvcMusicStore.Models.Genre>
?4?@{
?5?????ViewBag.Title?=?"Store";
?6?}
?7?<h3>Browse?Genres</h3>
?8?<p>
?9?????Select?from?@Model.Count()
10?????genres:
11?</p>
12?<ul>
13?????@foreach?(var?genre?in?Model)
14?????{
15?????????<li>@Html.ActionLink(genre.Name,
16?"Browse",?new{?genre?=?genre.Name?})</li>
17?????}
18?</ul>
? 重新生成項目,訪問 ?/Store/ :
? 查看源代碼:
2?<ul>3?????????<li><a?href="/store/Browse?genre=Disco">Disco</a></li>
4?????????<li><a?href="/store/Browse?genre=Jazz">Jazz</a></li>
5?????????<li><a?href="/store/Browse?genre=Rock">Rock</a></li>
6?</ul>
? 可以發現,解析出來的html代碼和預期的相同.
個人感悟
通過這章,可以發現,在mvc中,業務邏輯和表示層分離的程度非常高,幾乎可以同時開始編碼,而不用擔心其他問題.我們將在下一章介紹模型和數據訪問.
轉載于:https://www.cnblogs.com/mrzzcn/archive/2012/09/16/mvc-3.html
總結
以上是生活随笔為你收集整理的我的MVC之旅(3)--------MVC Music Store 第三篇 Views and ViewModels [翻译]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BT5 设置Ubuntu主题和字体
- 下一篇: 第十七章 特殊成员_类的函数指针