1、 ASP.NET网页代码模型11.1 Page类及页生命周期11.2 ASP.NET的事件驱动模型11.3 Request属性11.4 Response属性11.5 思考题11.6(1)ASP.NET文件扩展名可以在服务器执行的ASP.NET页面和在浏览器端执行的静态HTML网页最大的不同就是:在ASP.NET页面代码中包含了需要Web服务器识别和处理的元素。通常ASP.NET网页的文件扩展名为.aspx,静态HTML文件的扩展名为.htm或.html。在微软提供的Web服务器Internet 信息服务(IIS)的默认配置中,.aspx页面由ASP.NET运行,而.htm和.html页面则不在
2、服务器端运行。虽然开发者可以使用.aspx文件扩展名对任何HTML页进行重命名,然后该页将作为ASP.NET网页运行,但如果该页面中并不包含需要服务器处理的代码,则会无谓地增加页面处理的系统开销。因此,在基于ASP.NET开发的过程中,应该将动态网页的文件扩展名设置为.aspx,而静态网页文件的扩展名设置为.htm或.html。(2)指令ASP.NET页通常包含一些指令,这些指令在服务器端进行处理,通过这些指令可以设置属性和配置信息。最常用的指令为Page指令,该指令用来设置页面的多个属性,包括指定编程语言(C#或是VB.NET)、网页代码模型(单文件页面模型或是代码隐藏页面模型)、调试和跟踪
3、选项、关联的母版页(MasterPage)信息等。从代码中可以看出,该ASP.NET页选取C#作为开发语言,采用了代码隐藏页面模型(隐藏的代码文件为ProductEdt.aspx.cs),对应的类为ProductEdt,关联的母版页文件为“/Site.Master”。其它常用指令如下:l Import指令:指定要在代码中引用的命名空间。l OutputCache指令:指定Web服务器缓存此页面,还指定有关何时缓存该页面、将该页面缓存多长时间的参数。l Implements指令:指定页面实现.NET接口。l Register指令:注册其它控件以便在页面上使用。l Master指令:在母版页文件中
4、使用。l Control指令:在用户控件文件中使用。(3)form元素默认的情况,在VS中新增一个ASP.NET页面(Web Form页面),自动生成的代码中会包含一个form元素,这个form在用户与页面交互并向服务器提交数据的过程中起到非常关键的作用。它的作用机理在后文关于“状态管理”中会有进一步的解释。这个form元素在ASP.NET页面运行后确实会在HTML文件中生成标准的HTML form元素,但在ASPX源代码中需要符合以下规则:一个页面只能包含一个form元素。form元素必须包含runat=server的属性设置。需要执行回发的服务器控件必须位于form元素之内。form元素中
5、不包含action属性。服务器将在处理该页面时动态设置这一属性。(4)runat=server除了form元素,ASP.NET代码中可以放置多种具有runat=server属性的服务器控件和HTML元素。我们已经知道,在ASP.NET页面中可以添加允许用户与页面交互的服务器控件,包括按钮、文本框、列表等。这些服务器控件与HTML文件中的input元素类似,但却是在服务器上被处理。服务器控件还引发相应的服务器端事件,并且可以通过后台代码对其属性进行设置。ASP.NET服务器控件的标记名称通常以前缀asp:开头,包含runat=server属性和一个可选的ID,可以使用这个ID 在服务器代码中引用
6、该控件。(5)服务器端代码 ASP.NET支持多种语言编写服务器端代码,包括C#、Visual Basic、J#、Jscript和其它支持.NET的语言。ASP.NET服务器端代码由两种组成:元素标记和程序逻辑。元素标记包括HTML标记、服务器控件和静态文本等;程序逻辑包括各种事件处理程序和其它代码。如果将两种代码放在一个.aspx文件中,则称为单文件模型;如果两种代码分别放置在.aspx和.aspx.cs,则称为代码隐藏模型。下文中将分别介绍这两种网页代码模型。在单文件模型中,页的标记及其编程代码位于同一个扩展名为aspx的文件中。编程代码位于元素中,为了区别于HTML文件中的编程代码块,该
7、元素包含runat=server属性,即声明此处脚本程序将在服务器端执行。元素中定义了Web服务器控件Button1,设置了它的呈现方式(设置Text属性,即按钮上的文字,为Button)和行为方式(指定了它的onclick事件的处理函数为Button1_Click),而函数本身作为程序逻辑则被放置在元素中。总之,按钮的定义和相关的程序逻辑虽然在一个aspx文件中,但也被清楚地分别放在不同的区域。元素可以包含页中各个控件的事件处理函数、方法、属性等代码。单文件模型在运行时,aspx文件会被编译为Page类的一个派生类,并且实例化出一个页对象而被调用,页面中的各个控件会成为页的数据成员。void
8、 Button1_Click(Object sender,EventArgs e)Label1.Text=Clicked at +DateTime.Now.ToString();Single-File Page Model 通过代码隐藏模型,可以在aspx文件中保留网页中元素标记的定义和属性设置,并在aspx.cs文件(对于VB.NET语言则为aspx.vb文件)中编写程序逻辑。由于程序逻辑代码没有出现在aspx文件中,而是被分离和“隐藏”到aspx.cs文件中,因此,这种模型被称为代码隐藏模型。与单文件模式相同,最终这两部分会被合并编译为Page类的一个派生类。一个类被定义在两个(甚至更多个
9、)文件中,需要编程语言支持“分部类”机制。C#语言通过partial关键词提供了对分部类的支持。SamplePage.aspx文件中的代码如下:Code-Behind Page Model SamplePage.aspx.cs文件中的代码如下:using System;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;public partial class SamplePage:System.Web.UI.Page protected void Button1_Click(object sender,Ev
10、entArgs e)Label1.Text=Clicked at +DateTime.Now.ToString();Page类提供了由.aspx文件创建页面内所有对象的基本行为。由于Page类实现了IHttpHandler接口,可以作为HTTP请求的处理程序。Page的父类TemplateControl定义了页面(或控件)的基本功能,TemplateControl类的父类Control类定义了ASP.NET服务器端元素(包括页面、控件和用户控件)共享的属性、方法和事件。同时,TemplateControl类还实现了INamingContainer接口,使得Page类可以作为控件的容器。在Pag
11、e类的属性中,有几个常用的内置对象,包括:Request、Response、Application和Session等,它们会参与页面的运行和页面之间的信息传递。ASP.NET页面从被客户端请求、到运行、再到卸载的过程称为页的生命周期,在此期间,页将执行一系列处理步骤。了解页生命周期可以帮助开发者在生命周期的合适阶段编写代码以达到预期效果。从客户端请求开始,页要经历以下一系列阶段:l页请求:页请求是指用户通过浏览器向服务器请求特定的ASP.NET页。Web服务器将根据情况判断是否需要编译、是否发送缓存或者需要执行页面程序。l开始:在开始阶段将设置页的多个属性,包括Request、Response
12、、IsPostBack等属性。l页初始化:页初始化期间将设置页中的控件UniqueID属性,将主题应用于页。l加载:加载期间,判断如果当前请求是回发请求,则将根据之前的视图状态和控件状态恢复控件属性。l验证:在验证期间,将调用所有验证程序控件的Validate方法,以设置控件和页的IsValid属性。l回发事件处理:如果请求是回发请求,则将调用所有事件处理程序。l呈现:在呈现之前,会针对该页和所有控件保存视图状态,以供下一次回发时使用。l卸载:完全呈现页并已将页发送至客户端。将页面执行过程中产生的内置对象和其它数据成员进行删除,释放内存空间。基于面向对象程序的程序设计语言和开发环境大多支持事件
13、驱动模型,该模型可以使开发人员将主要的精力集中于针对程序运行的状态做出响应。比如在一个游戏中,玩家的下一个操作是很难预计的,程序只能根据发生的事件做出对应的处理。事件(Event)是一个信号,它告知应用程序有重要情况发生。例如,用户单击窗体上的某个控件时,窗体可能会引发一个 Click 事件并调用一个处理该事件的过程。参考前面“Default.aspx”文件中的一行代码:其中Onclick就是一个事件,当按钮被点击时产生事件。(1)执行效率 由于大多数ASP.NET服务器控件事件需要浏览器和服务器的往返行程才能进行处理,因此这些事件可能会影响页面的响应速度。为了避免产生过于频繁的浏览器、服务器
14、之间的数据交换,ASP.NET服务器控件不支持类似onmouseover这类事件,如果Web应用程序需要响应这类事件以构建所需的用户体验,则需要在浏览器端使用JavaScript进行程序设计。(2)事件参数 基于服务器的ASP.NET页和控件事件遵循.NET Framework事件处理程序方法的标准模式,所有事件都传递两个参数:表示引发事件的事件发送器对象,以及包含各种特定信息的事件对象。第二个参数通常是EventArgs类型,但对于某些控件而言是特定于该控件的类型。例如,对于ImageButton控件,第二个参数是ImageClickEventArgs类型,它包括有关用户单击位置的坐标的信息
15、。(3)服务器控件中的回发和非回发事件在服务器控件中,一些事件(比如Click事件)将会立即引发Form的提交,并将Form中各参数的值传递给服务器。通常这种Form提交都是指向当前页面本身,所以实际上是一种“回发”。另一些事件(如TextBox控件的Change事件)不会立即导致Form被提交,它们在下一次发生提交操作时引发。有时我们希望自己控制某个服务器控件的事件是否立即回发。比如,我们通过网页中的一系列CheckBox控件来收集用户的兴趣选项,我们希望当用户点击多个选项后再通过提交按钮一次性提交到服务器端;有时我们却希望当用户点击CheckBox控件按钮改变状态是立即在页面上做出反应,因
16、此希望CheckBox控件的CheckedChanged事件能够立即回发。默认情况下,CheckBox控件的CheckedChanged事件不会导致该页被提交。但是,如果将控件的AutoPostBack属性设置为true,则一旦用户单击该复选框,该页面便会立即被发送到服务器进行处理。(4)转发的事件GridView服务器控件是在设计数据库应用程序时最常用的控件之一,它包含了一个类似表格的区域,里面可以呈现多行、多列数据。通过程序设计,在GridView的表格中还可以包含按钮这一类控件,在这种情况下,并不会导致每个按钮各自引发一个事件,而是来自嵌套控件的事件被转发到容器控件。然后,容器通过事件的
17、参数来区分具体的情况,可以避免为每一个嵌套控件编写单独的事件处理程序。总之,对于事件的响应方式会直接影响到Web程序的性能,程序员可以结合浏览器端技术优化用户体验,要综合考虑开发效率和执行效率的平衡问题。(5)事件与处理函数的绑定事件消息与特定函数之间的绑定是通过事件委托来实现的。在设计时,开发者可以在控件标记中指定事件处理函数,例如下面代码中,将Button的OnClick事件绑定到名为Button1_Click的函数上。如果控件本身是在页面运行时中通过代码动态创建的,则不能使用上述绑定方法,因为在设计时还没有该控件的引用。Page.Request属性是HttpRequest类的实例对象,R
18、equest中包含了有关当前HTTP请求的信息。通过Request可以获得浏览器在Web请求期间发送的值,这些值有的是用户的输入,有的是客户端本身的信息。浏览器向服务器提交数据的方式分为两种,POST和GET。在POST方式中,数据是存在于请求报文体当中;另一种是通过GET方式,即所传输数据是在URL上直接输入的查询字符串来表达。由于两种方式的机理有所不同,所以对应到Request获取这些数据的方法就有所区别。如果浏览器采用POST方式传递数据,即在HTML中有如下的语句:则在服务器端WebForm1.aspx文件中需要使用下面的语句来获取数据:Request.Formabc如果浏览器采用GE
19、T方式传递数据,即在HTML中有如下的语句:http:/ void Page_Load(object sender,EventArgs e)/获取用户输入的信息 Response.Write(用户输入信息为:+Request.Formabc+);/获取浏览器端的信息 Response.Write(客户端IP:+Request.UserHostAddress+);Response.Write(浏览器:+Request.Browser.Browser+);Response.Write(浏览器版本:+Request.Browser.Version+);Response.Write(浏览器类型:+Re
20、quest.Browser.Type+);Response.Write(客户端操作系统:+Request.Browser.Platform+);Response.Write(是否支持Java:+Request.Browser.JavaApplets+);Response.Write(是否支持框架网页:+Request.Browser.Frames+);Response.Write(是否支持Cookie:+Request.Browser.Cookies+);Response.Write(JScript版本:+Request.Browser.JScriptVersion+);Response.Wr
21、ite(请求的虚拟路径:+Request.Path+);Response.Write(浏览器类型和版本:+Request.ServerVariablesHTTP_USER_AGENT+);Response.Write(用户的IP地址:+Request.ServerVariablesREMOTE_ADDR+);Response.Write(请求的方法:+Request.ServerVariablesREQUEST_METHOD+);Page.Response属性是HttpResponse 类的实例对象,该对象可以将HTTP响应数据发送到客户端,并包含有关该响应的相关信息。HttpResponse
22、封装了页面执行后返回到浏览器的输出,即是HTTP响应报文数据。Write函数的使用方法可以参考前文中的RequestForm.aspx.cs文件。下面例子展示了如何使用Redirect函数实现页面的跳转。首先在页面中放置DropDownList控件,其中预先设置多个选项。当用户选择其中选项并点击按钮提交后,程序将通过判断选项的值来确定调整的页面。RedirectForm.aspx文件的代码如下:请选择你要去的国家 USA UK France RedirectForm.aspx.cs文件的代码如下:protected void Button1_Click(object sender,EventA
23、rgs e)switch(DropDownList1.SelectedValue)case USA:Response.Redirect(US.htm);break;case UK:Response.Redirect(UK.htm);break;case France:Response.Redirect(France.htm);break;(1)什么是单文件模型,什么是代码隐藏模型,两种模型的区别是什么?(2)所有的aspx文件都会被编译为一个Page类的派生类。从客户端请求开始,Page对象要经历哪些阶段?(3)什么是事件驱动模型,如何避免事件驱动影响执行效率?(4)试举例说明Page对象中Request属性的作用。(5)试举例说明Page对象中Response属性的作用。