我的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中,业务逻辑和表示层分离的程度非常高,几乎可以同时开始编码,而不用担心其他问题.我们将在下一章介绍模型和数据访问.相关文章推荐
- 【翻译】MVC Music Store 教程-概述(三)
- 我的MVC之旅(4)-------Models and Data Access[翻译]
- 【翻译】MVC Music Store 教程-概述(二)
- MVC Music Store 在线音乐商店示例分析(13)View(Account、Checkout、Home、Shared、ShoppingCart)
- [Backbone]5. Model & View, toggle between Models and Views -- 2
- MVC Music Store 在线音乐商店示例分析(14)View(Browse、Details、GenreMenu、Create、 Edit、Delete、_ViewStart)
- 【翻译】MVC Music Store 教程-概述(一)
- MVC-REST-SilverLight 之 ViewModels\MainViewModel.cs
- 【翻译】Building a Simple Blog Engine with ASP.NET MVC and LINQ - Part 1
- Mvc项目实例 MvcMusicStore 五
- ASP.NET MVC Music Store教程(4):模型和数据访问
- 无限滚动AdapterViews and RecyclerView
- (apple官方文档译文)表视图样式和扩展视图-Table View Styles and Accessory Views
- MVC 的ViewBag, ViewData and TempData使用与区别
- Creating custom and compound Views in Android - Tutorial(翻译)
- MvcMusicStore学习中常出现的一个BUG
- Spring MVC and Excel file via AbstractExcelView
- ASP.NET MVC Music Store教程(5):编辑表单和模板
- MVC controller and View
- 将viewstate存储在数据库中并压缩 附代码(store viewstate in database and compress)