MVC 音乐商店 第 三 部分:Views 和 ViewModels
MVC 音乐商店是介绍,并分步说明了如何使用 ASP.NET MVC 和 Visual Studio 为 web 开发教程应用程序。
MVC 音乐商店是一个轻量级的示例存储实现它卖音乐专辑在线,并实现基本的网站管理、 用户登录,和购物车功能。
这个系列教程详细说明所有为构建
ASP.NET MVC 音乐商店示例应用程序采取的步骤。第 3 部分涵盖的意见和 ViewModels。
到目前为止我们都只已返回字符串从控制器操作。这是个不错的办法,把想法的控制器是如何工作的但它是不会要如何构建一个实际的 web 应用程序。我们要想更好的方法来生成 HTML 返回到浏览器访问我们的网站 — — 一个地方我们可以使用模板文件可以更轻松地自定义 HTML 内容发送回。这正是视图做的工作。
添加一个视图模板
若要使用一个视图模板,我们会更改 HomeController 索引方法,以返回一个,并让它返回 View(),像下面:
public class HomeController : Controller { // // GET: /Home/ public ActionResult Index() { return View(); } }
上述更改指示而不是返回一个字符串,我们反而要使用"视图"来生成结果回来。
我们现在将向我们的项目中添加适当的视图模板。为此,我们会将光标定位到 Index 操作方法内,然后右键单击并选择“添加视图”。这将会打开添加视图对话框中:
"添加视图"对话框允许我们能够快速、 轻松地生成视图模板文件。默认情况下"添加视图"对话框中预填充要创建,以便它匹配的操作方法,将使用它的视图模板的名称。因为我们使用的我们 HomeController Index() 操作方法内的"添加视图"上下文菜单,上面的"添加视图"对话框中有"指数"作为预先填充默认情况下的视图名称。我们不需要更改任何此对话框上的选项,因此请单击添加按钮。
当我们单击添加按钮时,Visual Web Developer 将创建新的 Index.cshtml 视图模板为我们在 \Views\Home 目录中,创建该文件夹,如果尚不存在。
"Index.cshtml"文件的名称和文件夹位置是重要的并遵循默认 ASP.NET MVC 的命名约定。目录名称、 \Views\Home、 匹配的控制器-被命名为 HomeController。该视图模板名称,索引,匹配的控制器操作方法,将会显示所需视图。
ASP.NET MVC 允许我们避免不必显式指定的名称或位置的视图模板,当我们使用此命名约定来返回一个视图。它将默认呈现 \Views\Home\Index.cshtml 视图模板时我们在我们的 HomeController 内写类似下面的代码:
public class HomeController : Controller { // // GET: /Home/ public ActionResult Index() { return View(); } }
可视化 Web 开发人员创建,并在我们单击"添加视图"对话框内的"添加"按钮后打开"Index.cshtml"视图模板。Index.cshtml 的内容如下所示。
@{ ViewBag.Title = "Index"; } <h2>Index</h2>
此视图使用 Razor 语法,这是比 ASP.NET Web 窗体和以前版本的 ASP.NET MVC 中使用的 Web 窗体视图引擎更简洁。Web 窗体视图引擎是在 ASP.NET MVC 3 中仍然可用,但许多开发人员会发现 Razor 视图引擎真的很适合 ASP.NET MVC 中发展。
前三行设置使用 ViewBag.Title 的网页标题。我们会看一看如何这工作更详细地很快,但第一次让我们更新文本标题文本,并查看的页面。更新要说"这是主页",如下所示的 < h2 > 标记。
@{ ViewBag.Title = "Index"; } <h2>This is the Home Page</h2>
运行,应用程序所示我们新的文本是可见的主页上。
使用常见的网站元素的布局
大多数的网站上有多个页面之间共享的内容: 导航、 页脚、 徽标图像、 样式表的引用等。Razor 视图引擎,这很容易地使用一个名为自动已为我们在 /Views/Shared 文件夹内创建的 _Layout.cshtml 页面管理。
双击该文件夹以查看的内容,其中如下所示。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>@ViewBag.Title</title> <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /> <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script> </head> <body> @RenderBody() </body> </html>
从我们个人的意见内容将显示由 @RenderBody() 命令中,和我们想要出现在这之外的任何常见内容可以添加到的 _Layout.cshtml 标记。我们希望我们的 MVC 音乐商店要到该网站中所有页上我们主页和存储区域有的链接具有共同的标头,所以我们将它添加到模板 @RenderBody() 声明的正上方。
<!DOCTYPE html> <html> <head> <title>@ViewBag.Title</title> <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" /> <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script> </head> <body> <div id="header"> <h1> ASP.NET MVC MUSIC STORE</h1> <ul id="navlist"> <li class="first"><a href="/" id="current">Home</a></li> <li><a href="/Store/">Store</a></li> </ul> </div> @RenderBody() </body> </html>
更新样式表
空项目模板包括一个非常精简的 CSS 文件,其中只包括用于显示验证消息的样式。我们的设计师提供了一些额外的 CSS 和图像来定义为我们的网站的外观和感觉,所以我们会添加那些在现在。
更新后的 CSS 文件和图像包含内容的目录中,这是可在 http://mvcmusicstore.codeplex.com 的 MvcMusicStore Assets.zip。我们会请他们两个在 Windows 资源管理器中选择和拖放到我们的解决方案在 Visual Web Developer 的内容文件夹,如下所示:
将要求您确认是否要改写现有的 Site.css 文件。单击是。
您的应用程序的内容文件夹中现在将显示如下:
现在让我们运行该应用程序,请参阅我们的更改外观的主页上。
- 让我们回顾一下发生了哪些变化:尽管我们的代码调用了“return View()”,HomeController 的 Index 操作方法仍然发现和显示 \Views\Home\Index.cshtml 视图模板,这是因为我们的视图模板遵循了标准命名约定。
- 在主页上显示一个在 \Views\Home\Index.cshtml 视图模板中定义的简单欢迎消息。
- 主页页面使用我们的 _Layout.cshtml 模板,并欢迎消息那么标准网站 HTML 布局内所载。
使用模型将信息传递到我们的视图
只是显示硬编码 HTML 视图模板并不能使一个非常有趣的 web 站点。若要创建一个动态的 web 站点,我们反而要将信息从我们的控制器操作传递到我们的视图模板。
在模型-视图-控制器模式中,术语“模型”是指表示应用程序中数据的对象。通常情况下,模型对象对应于您的数据库中的表,但他们没有到。
控制器操作方法,返回一个可以将一个模型对象传递给视图。这允许一个控制器干净地包上来来生成响应,然后将此信息传递到视图模板所需的所有信息,用来生成适当的 HTML 响应。这是最容易理解的看到它在行动中,让我们开始吧。
首先,我们将创建一些模型类来表示在我们店内的流派和专辑。让我们开始通过创建流派的类。右键单击"模型"文件夹在您的项目的范围内,选择"添加类"的选项,和命名文件"Genre.cs"。
然后将公共字符串名称属性添加到已创建的类:
public class Genre { public string Name { get; set; } }
注意: 在种情况下你想知道,{获取 ; 设置 ;} 表示法正在使用 C# 的自动实现的属性功能。这给了我们一个属性的好处而不需要我们来声明支持字段。
下一步,按照同样的步骤,创建一个专辑类 (名为 Album.cs),具有标题和体裁的属性:
public class Album { public string Title { get; set; } public Genre Genre { get; set; } }
现在我们可以修改 StoreController 使用视图,显示我们的模型中的动态信息。如果-出于演示的目的我们现在-命名为我们基于请求 ID 的唱片,我们可以显示该信息在下面的视图。
我们先通过更改存储详细信息操作,所以它显示为单个的专辑信息。要包括的 MvcMusicStore.Models 命名空间中,所以我们不需要每次我们想要使用的专辑类键入 MvcMusicStore.Models.Album 的StoreControllers类的顶部添加一个"使用"的语句。这类的"用法"部分现在应显示如下所示。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using MvcMusicStore.Models;
下一步,我们会去更新详细信息控制器操作这样,它返回一个,而不是字符串,像我们那样用 HomeController 的索引方法。
public ActionResult Details(int id)
现在我们可以修改专辑的对象返回到视图的逻辑。稍后在本教程中我们将会将数据从数据库中检索 — — 但现在,我们将使用"虚拟数据"来开始。
public ActionResult Details(int id) { var album = new Album { Title = "Album " + id }; return View(album); }
注意: 如果你不熟悉 C#,你可能会假定使用 var 意味着我们专辑变量是晚期绑定。那不是正确 — — C# 编译器使用基于我们要指定给该变量的类型推理来确定这张专辑是专辑的类型和编译作为专辑类型专辑本地变量,所以我们得到的编译时检查和 Visual Studio 代码编辑器支持。
现在,让我们创建一个视图模板,使用我们的专辑来生成 HTML 响应。我们这样做之前,我们需要生成项目,以便知道我们新创建的专辑类的添加视图对话框。您可以生成项目通过选择 Debug⇨Build MvcMusicStore 菜单项 (额外的学分,您可以使用 Ctrl-Shift-B 快捷方式要生成的项目)。
现在,我们已经设置了我们支持类,我们准备好建立我们的视图模板。详细信息方法内右键单击,然后从上下文菜单中选择"添加视图..."。
我们要创建一个新的视图模板,像我们之前和 HomeController。因为我们从 StoreController 中创建它它将默认情况下会生成 \Views\Store\Index.cshtml 文件中。
不同于之前,我们要检查"创建强类型"视图复选框。然后我们要选择我们"专辑"班内"视图数据-类"滴关于。这将导致"添加视图"对话框来创建一个视图模板,期望,对象将传递给它要使用的一张专辑。
当我们单击"添加"按钮时将创建我们的 \Views\Store\Details.cshtml 视图模板,包含以下代码。
@model MvcMusicStore.Models.Album @{ ViewBag.Title = "Details"; } <h2>Details</h2>
请注意第一行,该值指示此视图是强类型化为我们专辑类。Razor 视图引擎的理解它已被传递专辑的对象,所以我们会很容易访问模型属性,甚至在 Visual Web Developer 编辑器中的智能感知好处。
因此,它显示的相册标题属性通过修改这条线,如下所示显示更新的 < h2 > 标记。
<h2>Album: @Model.Title</h2>
注意当您输入 @Model 关键字以后, 期间显示的属性和专辑类支持的方法时触发智能感知。
让我们现在重新运行我们的项目,访问存储/详细信息/5 的 URL。我们会看到一张专辑像下面的详细的信息。
现在我们把一个类似更新存储浏览操作方法。因此它将返回一个更新方法和修改方法的逻辑,所以它将创建一个新的流派对象并将它返回到视图。
public ActionResult Browse(string genre) { var genreModel = new Genre { Name = genre }; return View(genreModel); }
在浏览方法中右键单击,然后从上下文菜单中,选择"添加视图..."然后添加是强类型的视图添加到体裁类的强类型。
更新 (/Views/Store/Browse.cshtml) 中查看代码中的 < h2 > 元素来显示类型排列的主题的信息。
@model MvcMusicStore.Models.Genre @{ ViewBag.Title = "Browse"; } <h2>Browsing Genre: @Model.Name</h2>
现在让我们重新运行我们的项目,然后浏览到/存储/浏览吗?流派 = 迪斯科 URL。我们会看到像下面显示的浏览页面。
最后,让我们向一个稍微复杂的更新的存储索引操作方法和视图,以显示我们存储区中的所有流派的列表。通过使用作为我们的模型对象,而不是只是一种单一的风格流派列表中,我们会这样做。
public ActionResult Index() { var genres = new List<Genre> { new Genre { Name = "Disco"}, new Genre { Name = "Jazz"}, new Genre { Name = "Rock"} }; return View(genres); }
存储索引操作方法中右键单击并选择添加视图,如前,选择流派作为模型的类,然后按添加按钮。
首先我们会更改 @model 声明,以表明视图将几个流派对象,而不是只是一个期待着。更改 /Store/Index.cshtml 阅读,如下所示的第一行:
@model IEnumerable<MvcMusicStore.Models.Genre>
这会告诉它将工作与可以容纳几个流派对象的模型对象,Razor 视图引擎。我们用 IEnumerable < 流派 > 而 < 流派 > 列表不因为它是更通用,允许我们稍后我们模型类型更改为任何支持 IEnumerable 接口的对象类型。
接下来,我们就会依次通过下面的已完成的视图代码中所示的模型中的体裁对象。
@model IEnumerable<MvcMusicStore.Models.Genre> @{ ViewBag.Title = "Store"; } <h3>Browse Genres</h3> <p> Select from @Model.Count() genres:</p> <ul> @foreach (var genre in Model) { <li>@genre.Name</li> } </ul>
注意到我们有充分的智能感知支持我们进入这段代码,这样当我们键入"@Model."我们看到所有方法和属性由 IEnumerable 类型体裁的支持。
在我们"foreach"循环中,Visual Web Developer 知道每个项目是的类型流派,所以我们看到 IntelliSence 为每个流派类型。
下一步,脚手架功能审查体裁对象,并确定每个将有一个 Name 属性,所以它循环,并将它们写。它还生成每个单独项目的详细信息,编辑、 删除链接。我们会好好利用,后来在我们店的经理,但现在我们想要一个简单的列表相反。
当我们运行该应用程序,浏览到 /Store 时,我们看到的计数和的流派列表将显示。
添加页面之间的链接
我们目前列出流派的 /Store URL 列出的体裁名称只是作为纯文本。让我们改变这这样而不是纯文本我们相反的体裁名称链接到适当的存储/浏览 URL,以便单击像"迪斯科"将定位到 /Store/Browse 一个音乐流派的? 流派 = 迪斯科 URL。我们可以使用类似下面的代码来更新 \Views\Store\Index.cshtml 视图模板,从而输出这些链接(不要键入在此 - 我们要去改进它):
<ul> @foreach (var genre in Model) { <li><a href="/Store/Browse?genre=@genre.Name">@genre.Name</a></li> } </ul>
这工作,但它可能会导致以后麻烦,因为它依赖于一个硬编码的字符串。例如,如果我们想要重命名控制器,我们必须搜索我们的代码来寻找需要更新的链接。
我们可以使用的另一种方法是利用 HTML 帮助器方法。ASP.NET MVC 中包含的 HTML 帮助器方法,可从我们查看模板代码,以执行各种常见的任务就是这样。Html.ActionLink() 帮助器方法是一个特别有用,可以轻松地生成 HTML < > 链接和照顾的令人讨厌的详细信息,如以确保 URL 路径正确的 URL 编码。
Html.ActionLink() 有几个不同的重载,以允许指定尽可能多的信息,您需要为您的链接。最简单的情况,您会提供只是链接文本和要转到客户端上单击超链接时的操作方法。例如,我们可以将链接到"/ 存储 /"存储详细信息页面的链接文本"去到存储索引"使用下面的调用 Index() 方法:
@Html.ActionLink("Go
to the Store Index", "Index")
注意: 在这种情况下,我们不需要指定该控制器的名称,因为我们只链接到所呈现的当前视图的同一控制器内的另一项行动。
我们将浏览页面的链接将需要传递参数,不过,所以我们会使用另一个重载的 Html.ActionLink 方法的采用三个参数:
- 1.链接文本,将会显示体裁名称
- 2.控制器的操作名称 (浏览)
- 3.路由参数值,指定 (风格) 的名称和值 (体裁名称)
放都在一起,在这里如何我们会写那些链接到存储索引视图:
<ul> @foreach (var genre in Model) { <li>@Html.ActionLink(genre.Name, "Browse", new { genre = genre.Name })</li> } </ul>
现在我们再次运行我们的项目并访问 /Store/ URL 时我们将会看到流派的列表。每个流派是一个超链接 — — 单击时它将会带我们去我们/存储/浏览? 流派 =[体裁] URL。
HTML 类型排列的主题列表中看起来像这样:
<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>