Web窗体编程
ASP.NET是建立在HTTP协议之上,利用HTTP命令和策略建立双向的、浏览器到服务器(B/S)的通信和协作。ASP.NET与其他Web开发技术的最大不同在于它所提出的抽象编程模型(Abstract Programming Model)——Web窗体模型。
Web窗体模型是ASP.NET实现的典型范式,浏览器将一个表单提交给Web服务器,然后会接收到返回的完整标记页面。
基于HTTP的事件驱动编程
ASP.NET的Web窗体将事件驱动模型的交互特性引入Web。在Web上实现事件模型,需要将与用户活动相关的所有数据发送到服务器端进行相应的状态处理。服务器会处理客户端发出的动作并做出反应。
应用程序的状态包括两种信息:客户端的状态和会话状态。客户端状态(主要是Web窗体中输入字段的内容,统称为“页面状态”)很容易通过存储于服务器端的已提交值的集合获取。但该怎么处理整个会话状态呢?客户端希望从一个页面发送到服务器的信息能够自然地与他/她稍后想要浏览的页面关联起来(例如将一件商品添加到购物车中)。该由谁来记录特定用户在购物车中购买的物品呢?HTTP本身不能跟踪这种信息,该项工作将由会话状态和集成了HTTP的服务器端基础架构来完成。这里必须强调一点,在进行Web开发时,理解无状态编程所涉及的概念非常重要。如前所述,HTTP是一个无状态的协议,这意味着同一会话的两次连续请求彼此不相干。这两次请求由最新实例化的环境分别进行解析,除了应用程序本身已经存储在全局对象中的信息外,新实例化的环境不会保存与会话有关的任何信息。
ASP.NET运行时在用户不同的页面请求期间记录页面的状态。在生成一个指定页面的HTML代码时,ASP.NET会对服务器端对象的状态进行编码,并将其保存在少数隐藏字段中。当请求该页面时,ASP.NET运行时引擎会检查存储在隐藏字段中的状态信息,并使用解码后的状态信息安装服务器端对象的新建实例。这种机制的实际效果与桌面应用程序上的Windows窗体模型相同,
Windows窗体模型与.NET Framework中Web窗体模型的对比
Windows窗体模型起源于典型的事件驱动桌面应用程序编程。不论客户端组件和服务器端组件之间存在怎样的连接,服务器端总会响应客户端的输入。服务器端知道整个应用程序的状态并以二层的连接方式进行操作。Web窗体模型需要某种机制来支持这种事件驱动编程模型。请求页面时要对状态执行反序列化,生成 HTML响应时要对状态执行序列化。
箭头表示典型的自顶向下的应用程序视角(从用户界面到系统服务) 在深入上图的各部分之前,先简单地回顾一下HTTP协议的一些基本概念(它仍然是Web交互的基础)。之后,我们会了解ASP.NET页面结构,以及如何编写和部署ASP.NET应用程序。
ASP.NET页面的结构
ASP.NET页面是服务器端的文本文件,以.aspx为扩展名存储。页面的内部结构是高度模块化的,包括以下独立的三部分:页面指令、代码区段和页面布局。
l)页面指令 页面指令用于建立页面的运行环境,规定HTTP运行时如何处理该页面,并对该页面的安全性进行设定。这些指令还允许导入命名空间,从而简化代码,加载当前不在全局程序集缓存(GAC)中的程序集,还可以用自定义的标签名和命名空间前缀来注册新的控件。
2)代码区段 代码区段包含页面和控件的事件处理程序,也可以包含一些辅助方法。所有与页面相关的源代码可以按内联方式编写,也可以单独存储在一个附属于该页面的文件中。如果按内联方式编写,则代码会放在<script>区段中。但这个名称(script,脚本)很容易让人误解(选择<script>这个名称是考虑到向后兼容的原因)。通过runat=server属性可以将服务器端的<script>标签与客户端的<script>标签区分开(后面还要对此进行讲解)。所有的页面代码在执行前会被编译。自ASP.NET 2.0开始,页面还可以进行预编译(precompile),以二进制程序集的形式进行部署。
3)页面布局 页面布局是指页面的“骨架”,包括服务器控件、文本、内联的JavaScript和HTML标签。服务器控件的界面(UI)可以用声明属性(attribute)和设置控件属 性(property)的方式加以完善。
要使页面能够运行,并不需要指定页面的所有部分。虽然实际的页面包括上述所有部分,但某些只包含代码区段或页面布局的页面,也可能是完全有效并可用的。在一些特殊情况下,ASP.NET页面甚至可以只由一条指令组成。
ASP.NET组件模型
ASP.NET运行时会将所请求的.aspx页面的源代码转换为.NET Framework类的实例,该类继承于基类Page。最后,运行中的一个ASP.NET页面是一个对象,它的某些组件(服务器控件)也是对象。
ASP.NET的许多新特性直接或间接衍生于.NET基础架构。ASP.NET受益于跨语言集成、异常处理、垃圾回收和代码访问安全功能,以及部署、配置和一个非常丰富的类库等特性。所有这些特性都不是自包含引擎的功能,之所以能使用这些特性,是因为ASP.NET应用程序也是一种特殊的.NET应用程序。
组件交互模型
在ASP.NET页面中,可以为标记有runat属性的任何组件指定一个唯一的ID,允许我们从服务器端访问。该方案可行是由于以下两个因素。
- .NET平台是基于组件的构架,且ASP.NET是该平台的组成部分。
- ASP.NET内建的应用程序状态管理机制。
.NET基于组件的设计使所有环境(包括ASP.NET应用程序)中的组件轻松而高效地交互。ASP.NET组件通过调用方法和设置属性来访问页面功能并进行交互。
实际上,页面中的所有元素都是组件,而不只是简单的可解析文本,这提供了一种灵活而又功能强大的模型。创建新控件就像派生出一个新类那样简单,构建一个新页面的继承层次也很简单,只需指定一个不同于基类Page的父类。
runat属性
runat属性决定着一段标记文本是在呈现时以纯文本方式表示,还是转换成具有状态的特定.NET类的实例。在后一种情况下,该类自身负责相关标记的生成。在ASP.NET页面中,所有带runat属性的元素会被当作服务器端控件处理。控件类所提供的方法和属性可用于对组件的状态进行配置。在准备向浏览器发送页面前,各控件自身会负责HTML代码的生成。
HTML服务器控件
HTML服务器控件是代表HTML标记的类,大多数浏览器都支持这些标记。HTML服务器控件属性集合与对应标签的常用属性集合相匹配。这种控件既有像InnerText、InnerHtml、Style和Value这样的属性,也有像Attributes这样的集合。每次在页面源代码中发现带有runat="server"的HTML标签时,ASP.NET运行时就会自动创建对应的HTML服务器控件的实例。
并非各种HTML规范支持的所有可用标签都能在现有的HTML服务器控件集合中找到。只有最常用的标签才能在System.Web.UI.HtmlControls命名空间中找到。<iframe>、<frameset>、<body>和<hn>之类的标签和<fieldset>、<marquee>和<pre>之类不常用的标签都被省略了。
要在服务器端使用及配置特殊的服务器控件时,所缺少的控件并不会限制程序员的编程能力。此时只需要使用一个泛化的编程接口(通过HtmlGenericControl类)。
Web服务器控件
与HTML服务器控件相比,Web服务器控件的功能更多。Web服务器控件不仅包括输入控件(如按钮和文本框等),还包括有特殊用途的控件(如日历、广告轮转器[ad rotator]、下拉列表、树状结构视图[tree view]和数据网格[data grid]等)。有些Web服务器控件与HTML服务器控件非常相似。但Web服务器控件比相应的HTML服务器控件更抽象,因为它们的对象模型不一定遵循HTML语法规则。
