我的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" >< 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 {  getset; }
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 {  getset; }
12          public Genre Genre {  getset; }
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.Album
3 
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.Genre
3 @{
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 >< 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 >< href ="/store/Browse?genre=Disco" >Disco </ a ></ li >
4          < li >< href ="/store/Browse?genre=Jazz" >Jazz </ a ></ li >
5          < li >< href ="/store/Browse?genre=Rock" >Rock </ a ></ li >
6  </ ul >

  可以發現,解析出來的html代碼和預期的相同.

個人感悟

通過這章,可以發現,在mvc中,業務邏輯和表示層分離的程度非常高,幾乎可以同時開始編碼,而不用擔心其他問題.我們將在下一章介紹模型和數據訪問.



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM