MVC音乐商店 - 第三部分:视图和视图模型

 

到目前为止,我们仅完成了从控制器返回简单的字符串,这是一个了解控制器如何工作的好途径,但这并不是我们想要的web应用程序。我们想要一个更好的方法来生成HTML(现在跑起来看下程序,是不是只有一行字符串呢?),使用模板文件可以更容易地定制发回的HTLM内容。这正是VIEW(视图)需要做的东西。

 

添加视图模板

若要使用一个视图模板,就需要修改HomeController中的Index方法,让他返回ActionResult,就像下面这样返回View():

public class HomeController : Controller
{
    //
    // GET: /Home/
    public ActionResult Index()
    {
        return View();
    }
}

 

上述的更改现在已经被替代,不是之前返回简单的字符串了,而是使用View生成结果,然后返回。

我们现在需要为项目添加一个视图模板,把光标停留在Index方法上面,单击右键,

 

“添加视图”对话框允许我们来快速、轻松的生成视图的模板文件。默认情况下,“添加视图”对话框将预先填写好模板里的内容,因此,当我们在控制器HomeController的Index方法中右键创建视图时,会默认使用当前动作方法的名称,我们不需要更改任何选项,所以请单击“添加”按钮。

 

点击添加按钮后,VS会在Views\Home目录中创建一个新的视图模板-Index.cshtml,如果没有Views文件夹,IDE环境将创建一个新的以Views命名的文件夹。

 

Index.cshtm”文件的名称及文件夹非常重要,遵循了ASP.NET MVC的约定。目录名称,\Views\Home匹配HomeController控制器,该视图模板名称-Index则匹配控制器的操作方法。

 

用 ASP.NET MVC 的命名约定来返回视图,可以让我们避免显示的去指定视图模板的名称和位置。当我们在HomeController中编写如下代码时,默认显示\Views\Home\Index.cshtml视图模板。

public class HomeController : Controller
{
    //
    // GET: /Home/
    public ActionResult Index()
    {
        return View();
    }
}

 

按下“添加视图”中的“添加”按钮后,VS将创建并打开Index.cshtml视图模板,Index.cshtml视图模板的内容如下所示:

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

 

视图使用了“Razor”,这是比ASP.NET及以前版本的ASP.NET MVC 中使用的Web Forms 引擎更简洁的语法。ASP.NET MVC 3 同时也支持Web Forms视图引擎(在视图引擎选择处有2个选项(Razor(cshtml)/ASPX(C#))),但很多的开发者发现Razor视图引擎比Web Forms引擎更适合ASP.NET MVC 的开发。

 

首三行用ViewBag.Title 设置页面的标题,我们将很快会看到他是怎样工作的,但现在我得改变视图页面的文本内容,新的内容要显示成-“这是主页!”,如下面的<h2>标签:

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

 

F5运行程序,我们将看到新的文本内容。

 

常用的网站元素布局

大多数的网站在多个页面之间有相同的内容:导航、页脚、Logo、样式引用等,Razor视图引擎也自动地在/Views/Shared文件夹下创建了一个_Layout.cshtml,他使我们更容易管理这些文件。

 

双击这个文件,显示内容如下:

<!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>
    @RenderBody()
</body>
</html>

 

@RenderBody()命令显示各自的内容,并且我们需要共用的内容都可以添加到_Layout.cshtml中。我们希望在MVC音乐商店所有的页面都有一个链接到Home和Store的头部,因此我们将他添加到模板中@RenderBody()中的前面(如外链JS文件)。

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("http://www.cnblogs.com/Content/Site.css")"rel="stylesheet" type="text/css" />
    <script src="@Url.Content("http://www.cnblogs.com/Scripts/jquery-1.4.4.min.js")"type="text/javascript"></script>
</head>
<body>
    <div id="header">
        <h1>
            ASP.NET MVC 音乐商店</h1>
        <ul id="navlist">
            <li class="first"><a href="/" id="current">主页</a></li>
            <li><a href="/Store/">商店</a></li>
        </ul>
    </div>
    @RenderBody()
</body>
</html>

 

更新样式表

新建项目里的CSS只是一个精简的,只包括用于显示验证消息。现在提供一些附件的css和图像来美化我们的网站外观。现在就去下载:MvcMusicStore-Assets.zip ,所有的样式脚本和图片都在MvcMusicStore-Assets文件夹里,将他们添加到项目里。

 

因为有相同名称的文件存在,提示是否覆盖现有文件,选择”是“

 

添加后的项目如下图所示

 

现在运行程序,看下更改之后的样子

 

现在看看做了哪些修改:

  • 按照视图模板默认的命名约定,HomeController的Index方法通过调用View()找到并显示\Views\Home\Index.cshtml视图模板
  • \Views\Home\Index.cshtml上定义了主页上显示的一条简单的信息
  • 在主页上使用了_Layout.cshtml模板,并且以html格式输出(浏览器里查看源代码)

使用模型(Model)把信息传递给视图

视图模板仅显示硬编码的HTML内容,这并不是一个有趣的web站点。若要创建一个动态的web站点,我们需要从控制器中传递信息到视图模板。

 

在Model-View-Controller(模型-视图-控制器)模式中,模型对象表示程序中的数据,通常情况下,模型对象对应于数据库中的表,但这里不是。

 

返回ActionResult的控制器方法可以把模型对象传递给视图,这使得控制器干净地封装了所有的信息,然后将这些信息传递给视图模板并生成适当的HTML。这是最简单的方式,让我们开始吧。

 

首先,我们创建一些模型类来描述音乐商店的类别和专辑,我们从Gener类开始。在项目中,右键单击“Models”文件夹,选择“添加 ->类”,并将文件命名为Genre.cs

 

然后将一个公用的字符串属性-Name添加到创建的类中

    public class Genre
    {
        public string Name { get; set; }
    }

 

注意:这里你可能会感到奇怪,{get;set;}是C#自动属性让我们方便定义属性而不需要声明字段。

下面,按刚才的步骤添加专辑类(Album.cs),他有两个属性:Title和Genre

public class Album
{
    public string Title { get; set; }
    public Genre Genre { get; set; }
}

 

现在,我们可以修改StoreController,使用视图显示模型信息

 

 我们通过修改控制器StoreController中的Details方法,让他显示单个专辑的信息。需要引用using MvcMusicStore.Models命名空间,在以后使用Album类时,就不需要每次都输入MvcMusicStore.Models.Album了,代码显示如下:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Web;
 using System.Web.Mvc;
 using MvcMusicStore.Models;

 

下一步,我们修改Details方法,让他返回ActionResult而不是返回字符串,像之前在HomeController的Index方法一样来修改他。

public ActionResult Details(int id)

 

现在我们可以修改用于相册中要使用到的Album对象,本教程后面我们会实现从数据库中取真实的数据来进行操作 ——但现在,我们将从“模拟数据”开始。

 public ActionResult Details(int id)
 {
    var album = new Album { Title = "Album " + id };
    return View(album);
 }

注意:您如果熟悉C#,您就会知道 var 可替代任何类型,因为编译器会根据上下文来判断您到底是想用什么类型,当在您无法确定自己将用什么类型时,就可以用var,类型Object,但效率比Object高点。(和原文不一致)

 

现在让我们给Album生成一个HTML响应的视图模板,在这之前,我们需要生成项目,以便让“添加视图”对话框知道我们要创建Alubm类。在“生成”菜单中选择“生成MvcMusicStore”(或者使用快捷键Ctrl+Shift+B)。

 

现在,我们已经设置好了支持的类,我们准备创建视图模板,单击右键,然后从菜单中选择“添加视图”。

 

我们要为Details创建一个视图模板,就像之前为HomeController创建视图模板一样,因为我们是在StoreController创建,他会默认生成生成\Views\Store\Details.aspx。

 

和先前不同的是,这次我们要把“创建强类型视图”选项勾上,然后在“视图数据类”下拉框中选择Album类,“添加视图”对话框将产生视图模板,并将Album对象传递给他。

 

当单击"添加"按钮时,将创建\Views\Store\Details.cshtml 视图模板,代码如下:

@model MvcMusicStore.Models.Album
@{
    ViewBag.Title = "Details";
}
<h2>Details</h2>

 

注意:第一行代码表示Album的强类型视图,使用Razor引擎可以让我们更容易访问模板属性,支持Visual Studio的“智能感应器”。

 

更新<h2>标签里的代码,显示Album的Title属性,如以下代码:

<h2>Album: @Model.Title</h2>

 

注意当输入@的时候,看智能提示中的属性与方法,现在运行程序,并访问 /Store/Details/5,我们将看到下面页面显示的内容:

 

现在我们同样来修改StoreController的Browse方法,修改方法的返回值为ActionResult,修改方法的业务逻辑返回一个Gener对象给视图。

        public ActionResult Browse(string genre)
        {
            var genreModel = new Genre { Name = genre };
            return View(genreModel);
        }

 

光标停留在Browse方法上,单击右键选择“添加视图”,添加一个Gener的强类型视图。

 

同样更新视图中(/Views/Store/Browse.cshtml)<h2>标签中的代码,如下:

@model MvcMusicStore.Models.Genre
@{
    ViewBag.Title = "Browse";
}
<h2>Browsing Genre: @Model.Name</h2>

 

运行项目,并访问 /Store/Browse?Genre=Disco,我们将看到以下页面:

 

是不是觉得前面的太简单了?现在,让我们做一个稍微复杂点的修改,让StoreController的Index方法和视图显示中所有的列表,我们这样做是使用Gener的集合而不是单个Gener对象。

        public ActionResult Index()
        {
            var genres = new List<Genre>
            {
                new Genre { Name = "流行"},
                new Genre { Name = "爵士"},
                new Genre { Name = "摇滚"}
            };

            return View(genres);
        }

 

在Index方法上单击右键,选择“添加视图”,类型选择Gener,按“添加确定”

 

首先,需要更改/Store/Index.cshtml里第一行的指令:

@model IEnumerable<MvcMusicStore.Models.Genre>

 

这将告诉Razor 引擎,他将不是对象而是一个集合,我是在使用 IEnumerable<Genre>,而不是 List<Genre> ,因为前者比后者通用,改变模板后,任何对象模型都将支持IEnumerable。

 

接下来,我们将循环Genre对象模型,如同下面的代码:

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

 

当我们输入“@”符号的时候需要注意IDE环境的智能感应出的属性及方法。

 

输入 /Store 运行项目,看下更新后的效果:

 

添加页面之间的链接

我们目前是把类别的名称作为纯文本列出。现在让我们用一个指向/Store/Browse 的链接来替换这些纯文本,比如在“流行”上点击时,可以链接到/Store/Browse?genre=流行页面,我们需要修改 \Views\Store\Index.cshtml视图模板,如下:

<ul>
    @foreach (var genre in Model)
    {
        <li><a href="/Store/Browse?genre=@genre.Name">@genre.Name</a></li>
    }
</ul>

 

可以运行,但他以后可能会出现问题,因为他依赖与硬编码。如果,重命名控制器,我们必须把相关的地方也修改。

 

一个可以改进的方法,利用HTML helper(帮助器)中的方法。ASP.NET MVC中包含的HTML helper(帮助器)方法运行我们从视图模板中执行这种常见的任务。Html.ActionLink() helper(帮助器)是一个特别有用的方法之一,可以方便的生HTML<a>标签和处理那些令人讨厌的细节,如,URL路径是正确的URL编码?

 

Html.ActionLink()方法有很多重载,允许我们选择我们所需要的链接。在这里,当链接被单击时,就链接到文本中去。例如,创建一个链接到Index的方法:

@Html.ActionLink("Go
to the Store Index", "Index")

 

注意:在这种情况下,我们不需要指定控制器的名称,因为我们是从当前的视图链接到同一个控制器里的另一个方法。

 

我们在链接页面时,需要传递参数,不过,我们可以用Html.ActionLink(),他有三个参数的重载:

  • 链接的文本—只用类型名称(gener.Name)
  • 控制器方法—Borwse
  • 路径参数值,指定的名称(gener)和值(gener.Name)

 

把这些都加起来,如下代码:

<ul>
    @foreach (var genre in Model)
    {
        <li>@Html.ActionLink(genre.Name,
"Browse", new { genre = genre.Name })</li>
    }
</ul>

 

现在再次运行项目,并访问/Store,我们可以看到类别列表,每个类别都是一个超链接,点击之后会链接进/Store/Browse?genre=[genre]

 

类型列表中的HTML如下所示:

<ul>
    <li><a href="/Store/Browse?genre=流行">Disco</a>
</li>
    <li><a href="/Store/Browse?genre=爵士">Jazz</a>
</li>
    <li><a href="/Store/Browse?genre=摇滚">Rock</a>
</li>
</ul>

 

第三部分总结: 

1.添加控制器:在Controller目录,单击右键,添加控制器即可;

2.添加视图:在控制器里,方法单击右键 ->添加视图,会在Views文件夹下以控制器命名文件夹下自动生成 方法名.cshtml的视图模板,.cshtml和以前写的.aspx差不多;

3._Layout.cshtml是公用模板,在Views\Shared文件夹下面,@RenderBody()是用来呈现各个视图模板的,显示通用的链接(详细在上面有介绍);

4.增加了样式,从官方网站中下载文件http://mvcmusicstore.codeplex.com下载,打开压缩包,把里面的文件复制到解决方案中(上面有详细介绍);

5.Model里新建了2个类(Genre/Album),Genre表示商品的类型,只有一个Name属性;Album类里有2个属性(Title/Genre)—>标题与音乐类型;

6.后面在Store的Index视图里增加超链接;

 

还记得这张图吗?

 

MVC音乐商店 - 第一部分:概述和新建项目

MVC音乐商店 - 第二部分:控制器

posted on 2012-09-13 17:31  Verms  阅读(869)  评论(0编辑  收藏  举报

导航