我的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