首先声明,在下英语水平不甚熟练(虽6级已过),因需要ASP.NET MVC 2.0 视图知识,借助Lingoes工具,翻了视图一章,只为英语水平在在下之下的同志做参考,但鼓励看原版。
从表面看,web应用从请求到输出是黑箱操作:输入URL,输出Html页面。路由,控制器和动作是MVC内部机制的重要部分,但是如果不产生HTML它们则是没有任何用处的。在
MVC架构中,视图对输出事关重大。
你已经在很多示例程序中看到过视图,你对它们做了什么也有了粗略的认识。现在就要关注且弄清楚这部分知识。能过阅读本章,你将会学到
- .aspx, 内联代码块,自动HTML编码在场景中是如何工作的。
- 该框架内置的HTML helper方法
- 怎样去创建可重用的视图片段(partials) ,和为它们传值方法不同方法。
视图怎样和ASP.NET MVC配合
大部分软件开发人员懂得最好是把UI代码和业务逻辑代码分开。否则,表现逻辑和应用逻辑将会纠缠在一起,追踪记录它们中的任一个都变成是不可能的。细微的改动可以轻易的引发大量分散bug的产生,然后生产力挥发了。MVC架构为解决这个问题,使视图保持独立,并强制的使它们简易。对于Web应用程序,视图只是用于控制器的输出,并使用间单化的表示逻辑来完成HTML的渲染。
然而,表现逻辑和业务逻辑的界线是主观的。如果你想要创建一个有交换灰颜色行的表格,它有可能是表现逻辑。但是如果你要高亮一个起过某一定数额的数字或是要隐藏一个国定假日呢?你或许会陷入争论-它有可能是一个业务规则,或者只是一个呈现功能,但是你不得不去选择。随着经验的积累,你能决定什么样的复杂程度你会发现在视图逻辑是可以接受的,或者必须把它们放到一个控制器或一个独立的组件能使你进行单元测试。
视图逻辑不如控制器逻辑那样可单元测试,因为视图输出文本而不是结构化的对象。因为这个原因。视图基本上不能进行单元试。
为视图添加内容
一个视图页完全可能只包括固定的,文字的HTML(加上一个<%@ Page %> 声明)
<%@ Page Inherits="System.Web.Mvc.ViewPage" %>
This is a very simple view.
你将会立即学到<%@ Page%> 声明。除去这些,上页的视图只中一些普通的旧的HTML。当然你也可以猜测这将会给予什么到浏览器。这个视图没有生成一个标记完好了HTML文档,它不包含或
标记,但是Web Forms视图引擎不知道或关心这个,它乐于提交任何字符串。添加动态内容到视图的五种方法
如果只是使用动态的HTML,你不会走的很远。你是在编写web业务应用程序。所以你需要一些代码使你的视图变为动态的。 MVC框架为向视图添加动态内容提供了一些机制。从快速且简单的到广泛且强大的,每次添加动态内容的方法将由你说了算。
使用内嵌代码:
假设你有一个视图页叫做ShowPerson.aspx,想要把一个Person类型的对象传入,如下面这样定义
Public class Person
{
Public int PersonId{get; set;}
Public string Name{get; set}
Public int Age{get; set ;}
Public ICollection
}
为了方便起见,当创建视图时,你或许会通过”View data class”选择一个把ShowPerson.aspx标记为一个强类型视图。
现在ShowPerson.aspx可以使用内嵌代码呈现一个Person类型的模型属性
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Information about <%: Model.Name %>
<%: Model.Name %> is
<%: Model.Age %> years old.
Children:
-
<%: child.Name %>, age <%: child.Age %>
<% foreach(var child in Model.Children) { %>
<% } %>
为什么内嵌代码在MVC视图里是一个好东西
内嵌代码在ASP.NET Web Forms是不受欢迎的因为Web Forms窗体页都应该代表一个服务器控件层次结构,而且不是一个HTML页。Web Forms是创建Windows窗体的错觉-GUI方式的开发,如果你使用了内嵌代码,你就会破坏掉错觉并且把所有人的游戏损坏。
但对于MVC 框架却不一样。它把web应用开发当作专门的权利,它不会去尝试模仿创建桌面应用的感受,所以它不需要保持任何这样的伪装。HTML是文本,并且用模板生成文本是很容易的事。这些年来许多的web开发平台来来去去,但是在不同的forms使用模板生成HTML却是不变的。这对于HTML很自然,并且工作的相当不错。
我理解你或许会问自已,“但是关注点分离是什么东西,我是否应该把逻辑和表现分开呢?”,绝对的!!!ASP.NET Web Forms和ASP.NET MVCX都尝试帮助开发人员把应用逻辑和表现分离开来。它们之间的不同在于到底分离点在哪个位置?
ASP.NET Web Forms 把声明性标记从程序性逻辑分离出来。 ASPX结尾文件包含声明性标记,操控和程序逻辑驱动在后台代码类中进行。那样不错-它真的在一定程序上分离了关注点。它的限制是在实践中,大约一半的后台代码隐藏类是和UI控件的控制相关联的,另外一半操作是与应用的域模型相关联。表现的关注点和应用关注点都聚焦到这个代码隐藏类上。
MVC框架之所以存在是因为我们前面课程中了解到传统的Web Forms和因为MVC驱动的web应用平台的益处吸引和已经在现在世界中得到了应用论证。它识别出了表现经常混入一些逻辑,所以最有价值的分割点是在应用逻辑和表现逻辑之间。控制器和域模型类掌控应用和域逻辑,视图掌管表现逻辑。只要表现逻辑保持的非常简单,它就会很清楚的放入到ASPX文件中。
开发人员使用ASP.NET MVC或别的基于MVC的web应用平台已经发现这是构建它们应用的非常有效的方式。在视图中使用if或者foreach是没有任何错误的。表现有时候不得不这样做。毕竟,只要保持它的简单性你就会得到很干净的应用。
理解MVC视图具体是怎样工作的
ASPX文件是如何编译的
每次你创建一个新的视图页,Visual Studio给你一个人ASPX页面。它是一个HTML模板,但是它包含内嵌代码和服务器控件。当你在你的服务器端调用一个Web Forms或者MVC应用。你将会调用一系列这些未经编译的ASPX或ASCX文件。尽管这样,当ASP.NET 在运行时需要每个文件时,它会使用特定的内置页编译来把这些文件翻译为一个真正的.NET类。
ASPX文件只是直接以<%@ Page%>开始。它指出,至少,你的ASPX页应该来自哪里,而且几乎总是指定的,你的为内嵌代码使用的.NET语言。
例如:
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
看一下视图页生成了什么样的代码
视编译为:
晦涩的细节:ASP.NET MVC 的本地编译器不明白Inherits指令中的C#格式的语法。这使你可能会发生疑问使用例如 Inherits=”System.Web.Mvc.ViewPage
我已经简化了反编译列表,但它仍然是一个准确的描述。关键要注意的是每一个HTML片段--换行符和其它的--变成了一个对 HtmlTextWriter.Write()的调用,你的内联代码只是简单的没改变的传递到__Render()方法中,所以它变成了呈现进程的一部分。服务器控件,像示例中的ImageServerControl,被解析出来并被当做编译成员变量,通过调用它们的RenderControl()方法在适当的点上面插入。
现在你不会对你的内联代码和服务器控件在运行时怎么调用产生不确定性了。
注意:当你在Visual Studio使用生成->生成解决方案时,你的方案被编译,并返回编译是否正确,然而,这个编译过程不包括ASPX和ASCX文件,因为它们在运行时编译。如果你想要你的视图在常规编译过程编译。你可以使用一个叫做
代码隐藏模型
如果你有使用ASP.NET Web Forms的经历,那么你对代码隐藏类就不会漠生,它的思想就是真接从System.Web.UI.Page继承代替生成页面。你可以建立一个中间基类(本身是从System.Web.UI.Page中派生的)并用它来承载其它代码,这将影响到该页面的行为。代码隐藏模型是为ASP.NET Web Forms设计的,它是Web Forms工作的主要方式:你使用代码隐藏类去承载定义在ASPX页面中服务器控件定义的事件。从技术上来讲,也可以使用Visual Studio来创建一个含有代码隐藏类的MVC视图,然后代码继承自Sytem.Web.Mvc.ViewPage或 System.Web.Mvc.ViewPage
然而,代码隐藏类是ASP.NET MVC基本上是没有必要的,因为在MVC的关注点分离思想下,视图应该保持简单,所以很少使用代码隐藏处理事件。
理解ViewData
你知道在ASP.NET MVC 中,控制器通过一个叫做ViewData的对象为视图提供数据,它是一个ViewDataDictionary类型。这个类型提供了两种方法去提交数据。
利用语义字典:每一个ViewDataDictionary是一个可输入任意键值对的字典,如(ViewData[“data”] = DateTime.Now)。每对的名字是一个字符串,每一个值是一个对象。
使用一个称为模型的属性:每一个ViewDataDictionary有一个叫做Model的特殊属性,它可以以持有任意对象。例如,ViewData.Model = myPerson。在你的视图里,你可以使用简化的表示ViewData.Model
第一个方法的价值是显而易见的,你可以传递任意数据集。第二个方法依赖于你的视图类型继承的类型。ASP.NET MVC给你两种视图页基类选择。
如果你的视图继承自ViewPage,你创建了一个松散类型视图。在这种情况下,ViewData.Model是一种非特异性类型对象,这非常的有用。如果你打算使用ViewData做为字典模型,松散类型的视图是特别合适的。
如果你的视图继承自ViewPage
实际上,如果你的视图页主要呈现一些域模型对象,你可以使用ViewData
输入控件
添加任意标记属性
<%=Html.TextBox(“myText”, “val”, new{someAttribute=”someval”})%>
将会呈现
提示:C#编译器不希望你使用C#保留字作为属性名字。所以,如果你想通过new{class=”myClass”}来呈现一个class属性,你会得到一个编译错误。为了防止这样,你需要在C#的保留字前面加上@如new{@class=”myClass”}。
呈现链接和URL
呈现下拉菜单和多选列表
在Microsoft.Web.Mvc.dll中额外赠送的帮助方法
ASP.NET MVC的未来组合中,Microsoft.Web.Mvc.dll,包含了一定数量的HTML辅助方法,它们还未加入到MVC Framework的核心中,可能是因为被考虑到不怎么重要或许还没有打磨好,但是在一些情况下还是很有用的。你可以从www.codeplex.com/aspnet下载该组件。确保你下载的是面向ASP.NET MVC 2。在你使用这些辅助之前,你需要添加这个引用,并且要修改Web.config文件,这样就可以把命名空间导入到你的每一个视图里。
做完了这些,你就可以使用下表中的辅助了
其它的HTMl辅助
呈现Form标记
框架也提供了呈现