开发人员之因此花费大量时间来重点设计控制器和模型对象,是由于在这些领域中,精心编写的整洁代码是开发一个可维护Web应用程序的基础。html
视图的职责是向用户提供用户界面。当控制器针对被请求的URL执行完合适的逻辑后,就将要显示的内容委托给视图。web
不像基于文件的Web框架,好比ASP.NET Web Forms和PHP,视图自己不会被直接访 问,浏览器不能直接指向一个视图并渲染它。相反,视图老是被控制器渲染,由于控制器为它提供了要渲染的数据。浏览器
在一些简单的状况中,视图不须要或须要不多控制器提供的信息。更常见的状况则是控制器须要向视图提供一些信息,因此它会传递一个数据转移对象,叫作模型。视图将这个模型转换为一个适合显示给用户的格式。在ASP.NET MVC中,完成这一过程由两部分操做,其中一个是检查由控制器提交的模型对象,另外一个是将其内容转换为HTML格式。安全
在最简单的状况中,向控制器发出一个请求,控制器返回一个视图,其实就是一些静态的HTML。很容易,可是动态性很差。前面说过,视图提供了一个模板引擎。下面咱们就利用这个模板引擎,从控制器向视图传递少许数据。最简单的方法就是使用ViewBag。ViewBag具备局限性,可是若是只是向视图传递少数数据,他仍是颇有用的。服务器
这与前面的Index方法几乎相同,可是注意控制器将ViewBag.Message属性值设置成一个字符串。而后再调用return View()。框架
这一节要介绍ASP.NET MVC如何找到正确的视图进行渲染,以及如何重写这个视图,为一个控制器操做指定特定的视图。布局
本章到如今为止介绍的控制器操做简单地调用return View()来渲染视图,还不须要指定指定视图的文件名。能够这么作,是由于它们利用了ASP.NET MVC框架的一些隐式约定,这些约定定义了视图选择逻辑。 网站
当建立新的项目模板时,将会注意到,项目以一种很是具体的方式包含了一个结构化的View目录。编码
在每一个控制器的View文件夹中,每一个操做方法都有一个同名的视图文件与其对应。这就提供了视图与操做方法关联的基础。spa
与ASP.NET MVC中的大部分约定设置同样,这一约定是能够重写的。若是想要Index操做方法渲染一个不一样的视图,能够向其提供一个不一样的视图名称。例如:
或
经过ViewBag向视图传递少许数据,尽管对于简单的状况,使用ViewBag很容易,可是处理实际数据时,ViewBag就变得不方便,这时就须要使用强类型视图。
咱们首先看一个不合适使用ViewBag的例子。没必要担忧要键入这些代码,它们只是用来进行说明的。
强类型视图容许设置视图的模型类型。所以,咱们能够从控制器向视图传递一个在两端都是强类型的模型对象,从而得到智能感知、编译器检查等好处。
对于在视图中常用的名称空间,一个较好的方法就是在Views目录下的web.config文件声明。
从技术角度讲,数据从控制器传送到视图是经过一个名为ViewData的ViewDataDictionary(这是一个特殊的字典类)。咱们可使用标准的字典语法设置或读取其中的值,实例以下:
ViewData["CurrentTime"]=DateTime.Now;
ViewBag是ViewData的动态封装器。这样咱们就能够按照下面的方式来设置值:ViewBag.CurrentTime=DateTime.Now;
所以,ViewBag.CurrentTime等同于ViewData["CurrentTime"]。
通常来讲,咱们将遇到的大部分代码使用ViewBag,而不是ViewData。 大多数状况下,这两种语法彼此之间并不存在真正的技术差别。ViewBag相对于字典语法而言仅仅是一种受开发人员欢迎、看上去很好看的语法而已。
ViewData和ViewBag
两者很明显的一个差别就是只有当要访问的关键字是一个有效的C#标识符时,ViewBag才起做用。例如,若是在ViewData["Key With Spaces"]中存放一个值,那么就不能使用ViewBag访问。由于这样根本就没法经过编译。
另外一个须要知道的重要差别就是,动态值不能做为一个参数传递给扩展方法。由于C#编译器为了选择正确的扩展方法,在编译时必须知道每个参数的正确类型。
若是其中任何一个参数是动态的,那么就不会经过编译。例如这行代码就会编译失败:
@Html.TextBox("name",ViewBag.Name).要使这行代码经过编译有两种方法:第一是使用ViewData["Name"]。第二种是把ViewData["Name"]值转换成一个具体的类型(string)ViewData["Name"]。
如刚才所述,ViewDataDictionary是一个特殊的字典类,而并不仅是一个通用的Dictionary。缘由之一在于,它有一个额外的Model属性,容许向视图提供一个具体的模型对象。由于ViewData中只能有一个模型对象,因此使用ViewDataDictionary向视图传递具体的类十分方便。这样一来,视图就能够指定他但愿哪一个类做为模型对象,从而让咱们可以利用强类型。
视图一般须要显示各类没有直接映射到域模型的数据。
把与视图主模型无关的数据存放在ViewBag属性中,能够很容易地实现这些数据在视图中的显示。当具备一个清晰定义的模型和一些额外的引用数据时,这种方法尤其有用。这种技术的一种常见的应用是使用ViewBag为下拉列表提供表单选项。例如,MVC Music Store项目的Album Edit视图须要填充Genres和Albums下拉列表,可是这些列表不适合放到Albums模型中。为了应对这些状况,同时不适用无关信息影响Album模型,咱们能够将Genre和Album的信息保存到ViewBag中。以下所示:
这么作固然可以完成要求,而且也为在视图中显示数据提供了一种灵活的方法。可是这并非一种应该常用的方法。通常应该坚持使用强类型模型对象————必须使全部数据都是强类型数据,以便视图编写人员可以利用智能感知功能。
如何建立视图呢?能够手动建立视图文件,而后把它添加在Views目录下。
显示添加视图对话框最简单的方法就是在操做方法上右击。
Razor视图引擎是ASP.NET MVC3中新扩展的内容,而且也是它的默认视图引擎。
Razor经过理解标记的结构来实现代码和标记之间尽量顺畅的转换。
不要过多地考虑
Razor的设计理念是简单直观。对于大多数应用,咱们没必要关心Razor语法----只须要在插入代码时,输入HTML和@符号。
Razor中的核心转换字符是“@”字符。这个单一字符用做标记-代码的转换字符,有时也反过来用做代码-标记的转换字符。
Razor表达式是用HTML自动编码的。
理解HTML和JavaScript编码的安全隐患是很重要的。不正确的编码会使网站和用户处在危险境地。
Razor在视图中除了支持代码表达式之外,还支持代码块。
代码块除了须要@符号分割以外还须要使用花括号。
<span>@model.Message</span>
Razor中的隐式代码表达式老是采用HTML编码方式。
代码表达式的值被计算并写入到响应中,这就是在视图中显示值的通常原理。
1 <span>1+2=@(1+2)</span>
有些状况下,须要显示地渲染一些不该该采用HTML编码的值,这是能够采用Html.Raw方法来保证该值不被编码。
<span>@Html.Raw(model.Message)</span>
不像代码表达式先求得表达式的值,而后再输出到响应,代码块是简单地执行代码部分。
1 @{ 2 int x=123; 3 string y="because."; 4 }
这个例子显示了Razor中混用文本和标记的概念:
1 @foreach(var item in items) 2 { 3 <span>Item @item.Name</span> 4 }
Razor查找的标签的开始位置以肯定什么时候将代码转换为标记。然而,有时可能想在一个代码块以后当即输出纯文本。例如,在下面的这个例子中就是展现如何在一个条件语句块中显示纯文本。
1 @if(showMessage){ 2 <text>This is plain text.</text> 3 }
或
1 @if(showMessage){ 2 @:This is plain text. 3 }
用"@@"来编码"@"以达到显示"@"的目的。
@**@
调用泛型方法的代码包括尖括号。
@(Html.SomeMethod<AType>())
Razor的布局有助于使应用程序中的多个视图保持一致的外观。
每个视图都是使用Layout属性来指定它的布局。若是多个视图使用同一个布局,就会产生冗余,而且很难维护。
_ViewStart.cshtml页面可用来消除这种冗余。这个文件中的代码咸鱼同目录下任何视图代码的执行。这个文件也能够递归的应用到子目录下的任何视图。
当建立一个默认的ASP.NET MVC项目时,你将会注意到在Views目录下会自动添加一个_ViewStart.cshtml文件,它指定了一个默认布局。
1 @{ 2 Layout="~/Views/Shared/_Layout.cshtml"; 3 }
由于这个代码优先于任何视图运行,因此一个视图能够重写Layout属性的默认值,从而从新选择一个不一样的布局。若是一组视图拥有共同的设置,那么_ViewStart.cshtml文件就有了用武之地,由于咱们能够在它里面对共同的视图配置进行统一设置。若是有视图须要覆盖统一的设置,咱们只须要修改对应的属性值便可。