您的位置:首页 > 其它

我的MVC之旅(3)--------MVC Music Store 第三篇 Views and ViewModels [翻译]

2012-09-16 13:30 543 查看

前言

有网友说不要浪费时间了赶紧干点正事,也有人觉得还不错;我个人觉得看懂是一回事,但是能够写出来分享是另一回事,这样记忆深刻有助于加深自己的理解,而且可以帮助有些和我一样的初学者,遇到的问题,怎么解决等等.

好了,下面开始正题.上周做完第二篇控制器之后,接下来就是第三篇 视图和模型了,源文章链接:http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-3

概述

本章通过简单的几个示例,介绍视图的使用方法以及控制器和视图之间的数据传递方法,简单而且直观,并且简单介绍了生成页面链接的方法.

内容

先来回顾一下:我们之前已经使用控制器返回String 类型的字符,这很好的让我们了解了控制器的工作原理,但是这不是真正的web应用程序.

我们想要一个更简单的方式返回HTML内容到浏览器--模版文件可以轻松地自定义HTML内容并发回浏览器,这就是视图.

1.添加第一个视图:

要应用视图,首先要改变HomeController 控制器的 Index方法的返回值为ActionResult,并且我们让他返回一个View();代码如下:

1
//

// GET: /Home/

public ActionResult Index()

{

return View();

}

上面的代码表示,我们想使用视图得到一个结果返回.

我们现在添加一个视图 到我们的项目里面,光标定位到Index()方法,右键单击选择添加视图:



添加视图对话框允许我们快速方便地生成视图文件,默认情况下,添加视图对话框已经为我们光标定位的控制器方法添加好了名称,我们不需要修改什么,直接点击确定,就会添加一个试图文件到工程目录:Views/Home/Index.cshtml.

视图文件的名字和目录非常重要,使用Mvc默认的命名规则,目录/View/Home 对应HomeController,文件Index.cshtml对应控制器方法:Index(). 使用这种命名规则,我们不用在Index()方法中显示指定视图文件,而是直接 return View().就像上面的HomeController.Index(),它将会自动引用View/Home/Index.cshtml.

添加完视图之后,默认会打开该视图文件,默认代码如下:

1 @{
ViewBag.Title = "Index";

}

<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 @{
ViewBag.Title = "Index";

}

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

<body>

@RenderBody()

</body>

</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>

<body>

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

@RenderBody()

</body>

</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

{

public string Name { get; set; }

}

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
{
public string Title { get; set; }
public Genre Genre { get; set; }
}
}
现在,我们可以修改StoreController 使用视图从模型显示动态信息,我们给Albums一个和Request ID相同的名字(演示起见).

首先:打开StoreController.cs,修改Details 方法,让它显示一个相册的信息,引入MuvMusicStore.Models命名空间以便于使用相关模型类,修改Detail的返回值类型:string to ActionResult,修改方法逻辑:返回一个Album对象给View(稍后我们会讲如何从数据库检索数据), 但是现在我们将使用“模拟数据”.

给Details添加视图文件,不过这个步骤要复杂一点点,在添加视图对话框里我们要勾选“创建强类型视图” 然后在下面选择 Album (MvcMusicStore.Models),如果下拉框里面没有选项,请重新生成项目后重试,支持模版就用Empty ,勾选 引用脚本库,点击确定我们会看到生成的视图文件如下:

@model MvcMusicStore.Models.Album

@{
ViewBag.Title = "Details";
}

<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方法:

public ActionResult Browse(string genre)
{
var genreModel = new Genre { Name = genre };
return View(genreModel);
} 给Browse 添加视图,强类型关联到Genre

更新Browse.cshtml代码:

@model MvcMusicStore.Models.Genre
@{
ViewBag.Title = "Browse";
}
<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"},
new Genre { Name = "Rock"}
};
return View(genres);
} 给Index添加视图强类型管理到Genre,打开视图文件Models/Store/Index.cshtml,把第一行的接收参数生命更新:

@*注释*@
@*@model MvcMusicStore.Models.Genre *@
@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()
genres:
</p>
<ul>
@foreach (var genre in Model)
{
<li>@genre.Name</li>
}
</ul> 任然有非常强悍的智能感知:比如输入@Model会出来所有支持的成员;

循环内部,每个 var生命的genre 也可以智能感知所有的成员;

现在我们已经可以循环传入对象列表,并输出对象总数以及每个对象的信息,以后我们会生成编辑、查看详细信息和删除操作到每一项,现在我们先来看看简单列表:

重新生成项目,访问 /Store:



4.添加站内链接

刚才的 /Store页面展示了一组Genre对象的Name属性作为普通文本,我们给他们加上链接,通过点击访问相关的详细信息/Store/Browse,当我们点击 "Disco",能够跳转到/Store/Browse?genre=Disco,我们更新/Views/Store/Index.cshtml的代码:

<ul>
@foreach (var genre in Model)
{
<li><a href="/Store/Browse?genre=@genre.Name">@genre.Name</a></li>
}
</ul> 这样可以实现,但是不是很好的方式,比如我们要更新Browse为BrowseDetail,那就需要检索整个项目来查找需要更新的地方.

另一个实现方式就是利用 HTML Helper 方法.Asp.net Mvc包含HTML Helper方法,在View编辑器中,我们可以使用它来完成相关的任务. Html.ActionLink()是一个特别有用的方法,使用它创建链接,维护路径,还是确保URL编码都比较简单,

Html.ActionLink()有几个重载允许我们传入需要的各种参数, 在示例中我们仅需要提供链接文本和目标Action,比如我们可以在Store Details 页面点击"Go to Store Index" 连接到"/Store"页面,用法如下:

@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()
genres:
</p>
<ul>
@foreach (var genre in Model)
{
<li>@Html.ActionLink(genre.Name,
16 "Browse", new { genre = genre.Name })</li>
}
</ul> 重新生成项目,访问 /Store/ :



查看源代码:

<ul>
<li><a href="/store/Browse?genre=Disco">Disco</a></li>
<li><a href="/store/Browse?genre=Jazz">Jazz</a></li>
<li><a href="/store/Browse?genre=Rock">Rock</a></li>
</ul> 可以发现,解析出来的html代码和预期的相同.

个人感悟

通过这章,可以发现,在mvc中,业务逻辑和表示层分离的程度非常高,几乎可以同时开始编码,而不用担心其他问题.我们将在下一章介绍模型和数据访问.


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: