3.1 添加一个视图
在本节中我们修改HelloWorldController类,以便使用视图来向客户端展示HTML格式的响应结果。我们使用ASP.NET MVC3中新增的Razor视图引擎来创建视图。Razor视图模板文件的后缀名为.cshtml,它提供了一种简洁的方式来创建HTML输出流。Razor视图大大减少了在书写视图模板文件时所需要输入的字符,提供了一个最快捷,最简便的编码方式。
这里,我们在HelloWorldController类的Index方法中添加使用一个视图。在修改前的Index方法中返回一个字符串,我们修改这个方法来使它返回一个视图,代码如下所示。
public ActionResult Index()
{
return View();
}
这段代码表示Index方法使用一个视图模板来在浏览器中生成HTML格式的页面文件。接着,让我们来添加一个Index方法所使用的视图模板。在Index方法中点击鼠标右键,然后点击“添加视图”,将会弹出一个“添加视图”对话框。
图3-1 添加视图
图3-2 添加视图对话框
在该对话框中,不做任何修改,直接点击添加按钮,观察解决方案资源管理器中,在MvcMovie项目下的Views文件夹下创建了一个HelloWorld文件夹,并且在该文件夹中创建了一个Index.cshtml文件,同时该文件呈打开状态,如图3-3所示。
图3-3 视图模板文件被创建并呈打开状态
让我们在该文件中追加一些文字,代码如代码清单3-1所示。
代码清单3-1 Index.cshtml视图模板文件
@{
ViewBag.Title = "首页";
}
<h2>首页</h2>
<p>这是我的第一个视图模板</p>
运行应用程序,输入地址“http://localhost:xxxx/HelloWorld”。由于在Index方法中并没有做任何事情,只是简单地一行代码—“return View()”,该行代码表示我们使用一个视图模板文件来在浏览器中展示响应结果。因为我们并没有显式指定使用哪个视图模板文件,所以使用了默认的Views文件夹下的HelloWorld文件夹下的Index.cshtml视图模板文件。该视图模板文件中只有简单的两行文字,在浏览器中的显示结果如图3-4所示。
图3-4 在浏览器中显示视图
看上去还不错,但是请注意,该网页的标题为“首页”,但是网页中的大标题文字却为“我的MVC应用程序”,需要修改一下。
3.2 修改视图,修改应用程序的页面布局
首先,让我们修改页面大标题中的“我的MVC应用程序”文字。这段文字是所有页面中的公共大标题,在这个应用程序中,虽然所有页面中都显示了这个共同的大标题,但只有一处地方对其进行了设置。打开解决方案资源管理器中Views文件夹下的Shared文件夹下的_Layout.cshtml文件。该文件被称为布局页面,位于公有文件夹Shared下,被所有其他网页所共用。
图3-5 公有布局页面
布局模板页允许你统一在一个地方指定整个Web应用程序或Web网站的所有HTML页面的布局方法。请注意文件底部的“@RenderBody()”代码行。@RenderBody()是一个占位符,代表了所有你创建出来的实际应用的视图页面,在这里统一指定。将布局模板文件中的“我的 MVC 应用程序”修改为“我的 MVCMovie 应用程序”。代码如下所示。
<div id="title">
<h1>我的 MVCMovie 应用程序</h1>
</div>
运行应用程序,注意网页中的大标题被修改为“我的 MVCMovie 应用程序”。点击“关于”链接,你可以看见“关于”页面中的大标题也被修改为“我的 MVCMovie 应用程序”。由此可以看出一旦修改了布局页面中的某处地方,该修改将会被应用到所有页面中。
图3-6 在布局页面中修改了网页中显示的大标题
完整的_Layout.cshtml文件中的代码如代码清单3-2所示。
代码清单3-2 _Layout.cshtml文件中的完整代码
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; 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.4.4.min.js")"
type="text/javascript"></script>
</head>
<body>
<div class="page">
<div id="header">
<div id="title">
<h1>我的 MVCMovie 应用程序</h1>
</div>
<div id="logindisplay">
@Html.Partial("_LogOnPartial")
</div>
<div id="menucontainer">
<ul id="menu">
<li>@Html.ActionLink("主页", "Index", "Home")</li>
<li>@Html.ActionLink("关于", "About", "Home")</li>
</ul>
</div>
</div>
<div id="main">
@RenderBody()
<div id="footer">
</div>
</div>
</div>
</body>
</html>
现在,让我们修改Index视图页面的标题。
打开Views文件夹下的HelloWorld文件夹下的Index.cshtml文件。这里我们修改两处地方:首先,修改浏览器中的标题,然后修改<h2>标签中的小标题文字。修改后代码如代码清单3-3所示。
代码清单3-3 修改后的Index.cshtml视图模板文件
@{
ViewBag.Title = "电影清单";
}
<h2>我的电影清单</h2>
<p>这是我的第一个视图模板</p>
ViewBag对象的Title属性代表了显示该页面时的浏览器中的标题文字。让我们回头看一下布局模板文件,在该文件的<head>区段中的<title>标签中使用了这个值来作为浏览器中的网页标题。同时,通过这种方法,你可以很容易地在你的视图模板文件与布局模板文件之间进行参数的传递。
运行应用程序,在地址栏中输入“http://localhost:xxxx/HelloWorld”,注意浏览器中的网页标题,页面中的小标题文字都变为修改后的标题文字(如果没有发生变化的话,则可能你的网页被缓存住了,可以按Ctrl+F5键来在重新刷新页面时取消缓存)。
同时也请注意_Layout.cshtml文件中的占位符中的内容被替换成了Index.cshtml视图模板中的内容,所以浏览器中展示的是一个单一的HTML文件。浏览器中的运行结果如图3-7所示。
图3-7 修改了标题后的Index视图模板文件
此处,我们的数据(“这是我的第一个视图模板”文字)是被直接书写在文件中的,也就是说我们使用到了MVC应用程序的“V”(视图View)与“C”(控制器Controller)。接下来,我们讲解一下如何创建一个数据库并从该数据库中获取模型数据。
3.3 将控制器中的数据传递给视图
在我们使用数据库并介绍模型之前,首先我们介绍一下如何将控制器中的信息传递给视图。浏览器接收到一个URL请求后,将会调用控制器类来进行响应。你可以在控制器类中进行对接收到的页面参数进行处理的代码,你可以在控制器类中书写从数据库中获取数据的代码,你也可以在控制器类中书写代码来决定返回给客户端什么格式的响应文件。控制器可以利用视图模板文件来生成HTML格式的响应文件并显示在浏览器中。控制器类负责提供视图模板文件在生成HTML格式的响应文件时所需要的任何数据或对象。一个视图模板文件不应该执行任何业务逻辑,也不应该直接和数据库进行交互。它只能和控制器类进行交互,获取控制器类所提供给它的数据,这样可以使你的代码更加清晰,容易维护。
现在在我们的应用程序中,HelloWorldController控制器类中的Welcome方法带有两个参数—name与numTimes,Welcome方法直接向浏览器输出这两个参数的参数值。这里,我们修改该方法使其不再直接输出数据,而是使用一个视图模板。该视图模板将生成一个动态的响应流,这意味着我们需要将数据从控制器类传递给视图以便利用该数据来生成该响应流。我们在该控制器类中将视图模板所需要的数据送入一个ViewBag对象中,该对象可以被视图模板直接接收。
打开HelloWorldController.cs文件,修改Welcome方法,在该方法中为ViewBag对象添加一个Message属性与NumTimes属性,并且将属性值分别设定为经过处理后的name参数值与numTimes参数值。ViewBag对象是一个动态对象,你可以为它添加任何属性并赋上属性值。在未赋值之前该属性是不生效的,直到你赋值为止。修改后的HelloWorldController.cs文件中的代码如代码清单3-4所示。
代码清单3-4 修改后的HelloWorldController.cs文件
using System.Web;
using System.Web.Mvc;
namespace MvcMovie.Controllers
{
public class HelloWorldController : Controller
{
//
// GET: /HelloWorld/
public ActionResult Index()
{
return View();
}
//
// GET: /HelloWorld/Welcome/
public ActionResult Welcome(string name, int numTimes = 1)
{
ViewBag.Message = "Hello " + name;
ViewBag.NumTimes = numTimes;
return View();
}
}
}
现在ViewBag对象中已经包含了数据,它将被自动传递给视图。
接下来,我们需要创建一个Welcome视图模板。在“调试”菜单中,点击“生成 MvcMovie”将应用程序进行编译,如图3-8所示。
图3-8 编译应用程序
接下来,在Welcome方法中点击鼠标右键,然后点击“添加视图”,弹出对话框如图3-9所示。
图3-9 为Welcome方法添加视图
在该对话框中不做任何修改,直接点击添加按钮, View文件夹下的HelloWorld文件假种自动被创建了一个Welcome.cshtml文件,打开该文件,在<h2>元素下添加代码,让浏览器显示URL地址中传入的name参数中设定的文字,显示次数等于URL地址中传入的numTimes参数中设定的次数。修改后的Welcome.cshtml文件中的代码如代码清单3-5所示。
代码清单3-5 修改后的Welcome.cshtml文件
@{
ViewBag.Title = "Welcome";
}
<h2>Welcome</h2>
<ul>
@for (int i = 0; i < ViewBag.NumTimes; i++)
{
<li>@ViewBag.Message</li>
}
</ul>
运行应用程序,并且在地址栏中输入“http://localhost:xx/HelloWorld/Welcome?name=Scott&numtimes=4”,该地址栏中的页面参数将会自动传递给控制器。控制器将会把这些参数值放入ViewBag对象中并且传递给视图。视图再在浏览器中显示这些数据。
图3-10 视图中显示从控制器类中传递过来的数据
这里,我们使用了模型“M”的一种方式,但是不是数据库的方式。在下一节中,我们将创建一个数据库,并且介绍如何对该数据库中的数据进行处理。