none
ASP.NET编程模型 RRS feed

  • 常规讨论

  • ASP.NET教程系列1-ASP.NET编程模型

     

    一、HTTP协议:
    1、HTTP协议是什么
    我们在浏览器的地址栏里输入的网站地址叫做URL(UniformResourceLocator,统一资源定位符)。就像每家每户都有一个门牌地址一样,每个网页也都有一个Internet地址。当你在浏览器的地址框中输入一个URL或是单击一个超级链接时,URL就确定了要浏览的地址。浏览器通过超文本传输协议(HTTP),将Web服务器上站点的网页代码提取出来,并翻译成漂亮的网页。因此,在我们认识HTTP之前,有必要先弄清楚URL的组成,例如:
    http://www.microsoft.com/china/index.htm。它的含义如下:

    • http://:代表超文本传输协议,通知microsoft.com服务器显示Web页,通常不用输入;
    • www:代表一个Web(万维网)服务器;
    • Microsoft.com/:这是装有网页的服务器的域名,或站点服务器的名称;
    • China/:为该服务器上的子目录,就好像我们的文件夹;
    • Index.htm:index.htm是文件夹中的一个HTML文件(网页)。

    我们知道,Internet的基本协议是TCP/IP协议,然而在TCP/IP模型最上层的是应用层(Applicationlayer),它包含所有高层的协议。高层协议有:文件传输协议FTP、电子邮件传输协议SMTP、域名系统服务DNS、网络新闻传输协议NNTP和HTTP协议等。HTTP协议(Hypertext Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。这就是你为什么在浏览器中看到的网页地址都是以“http://”开头的原因。
    2、HTTP工作原理
      由于HTTP协议是基于请求/响应范式的(相当于客户机/服务器)。一个客户机与服务器建立连接后,发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。

      许多HTTP通讯是由一个用户代理初始化的并且包括一个申请在源服务器上资源的请求。最简单的情况可能是在用户代理和服务器之间通过一个单独的连接来完成。在Internet上,HTTP通讯通常发生在TCP/IP连接之上。缺省端口是TCP80,但其它的端口也是可用的。但这并不预示着HTTP协议在Internet或其它网络的其它协议之上才能完成。HTTP只预示着一个可靠的传输。

      在WWW中,“客户”与“服务器”是一个相对的概念,只存在于一个特定的连接期间,即在某个连接中的客户在另一个连接中可能作为服务器。基于HTTP协议的客户/服务器模式的信息交换过程,它分四个过程:建立连接、发送请求信息、发送响应信息、关闭连接。

      

    其实简单说就是任何服务器除了包括HTML文件以外,还有一个HTTP驻留程序,用于响应用户请求。你的浏览器是HTTP客户,向服务器发送请求,当浏览器中输入了一个开始文件或点击了一个超级链接时,浏览器就向服务器发送了HTTP请求,此请求被送往由IP地址指定的URL。驻留程序接收到请求,在进行必要的操作后回送所要求的文件。在这一过程中,在网络上发送和接收的数据已经被分成一个或多个数据包(packet),每个数据包包括:要传送的数据;控制信息,即告诉网络怎样处理数据包。TCP/IP决定了每个数据包的格式。如果事先不告诉你,你可能不会知道信息被分成用于传输和再重新组合起来的许多小块。

      也就是说商家除了拥有商品之外,它也有一个职员在接听你的电话,当你打电话的时候,你的声音转换成各种复杂的数据,通过电话线传输到对方的电话机,对方的电话机又把各种复杂的数据转换成声音,使得对方商家的职员能够明白你的请求。这个过程你不需要明白声音是怎么转换成复杂的数据的。

    3、ASP.NET下HTTP协议分析
    HTTP请求
    我们首先创建一个aspx页面仅拖上来一个按钮和一个文本框,打开Fiddler(这是一款微软员工开发的HTTP调试工具,下载地址http://www.fiddlertool.com/),然后浏览刚才创建的页面。查看Fiddler我们会看到:

    上面框的内容其实就是当你敲入地址按回车后浏览器提交到服务器的内容,服务器就是拿到这些信息后进行解析,然后根据你的请求提供给你相应的页面,我们先对这里的内容进行简单的介绍:

    • GET:它后面跟随一个网页的位置,服务器接受请求并返回其请求的页面。除了页面位置作参数之外,请求还可以跟随协议的版本如HTTP/1.0等作为参数,以发送给服务器更多的信息。
    • Accept-Language: 当前浏览器语言
    • Host:指定请求资源的Intenet主机和端口号,必须表示请求url的原始服务器或网关的位置。HTTP/1.1请求必须包含主机头域,否则系统会以400状态码返回。
    • User-Agent:包含发出请求的用户信息,这里标识发出该请求的浏览器的类型。
    • Connection:关闭一个连接或保持一个连接有效

    HTTP响应

    服务器响应包括一个状态行,该状态行由消息的协议版本和一个退出码(表示成功或发生错误)组成。状态行后面跟着几个报头(通常是页面的内容类型和长度)和主体内容。一个空行将主题内容与消息的其余内容分开。如下图就是刚才访问页面的响应内容:

    服务器响应包括一个状态行,该状态行由消息的协议版本和一个退出码(表示成功或发生错误)组成。状态行后面跟着几个报头(通常是页面的内容类型和长度)和主体内容。一个空行将主题内容与消息的其余内容分开。如下图就是刚才访问页面的响应内容:

    第一行的代码200指示该请求一切正常,server内容为服务器信息,Content-Type用于向接收方指示实体的介质类型,指定HEAD方法送到接收方的实体介质类型,这里提供的意思为编码为utf-8的文本格式。

    二、ASP.NET页面构成

    ASP.NET页面主要包括三个部分:页面指令,代码和页面布局
    页面指令:页面指令建立该页面的运行环境,规定HTTP运行库如何处理该页面
    代码:包含页面和控件事件的处理程序,如果我们使用代码隐藏的话一般不会出现。
    页面布局:页面布局表示页面的框架包括服务器控件、文本和HTML标签。

    例子:

    页面例子
    <%@ Page Language="C#" %><!--页面指令-->

    <script runat="server"><!--代码-->
    void Button1_Click(Object sender, EventArgs e)
    {
    Label1.Text = "Clicked at " + DateTime.Now.ToString();
    }
    </script>

    <html><!--页面布局-->
    <head>
    <title>Single-File Page Model</title>
    </head>
    <body>
    <form runat="server">
    <div>
    <asp:Label id="Label1"
    runat="server" Text="Label">
    </asp:Label>
    <br />
    <asp:Button id="Button1"
    runat="server"
    onclick="Button1_Click"
    Text="Button">
    </asp:Button>
    </div>
    </form>
    </body>
    </html>

    三、ASP.NET页面生命周期

    ASP.NET 页运行时,此页将经历一个生命周期,在生命周期中将执行一系列处理步骤。这些步骤包括初始化、实例化控件、还原和维护状态、运行事件处理程序代码以及进行呈现。了解页的生命周期非常重要,这样就能在合适的生命周期阶段编写代码,以达到预期效果。此外,如果开发自定义控件,则必须熟悉页生命周期,从而正确地初始化控件,使用视图状态数据填充控件属性以及运行所有控件行为逻辑。

    1、对象初始化Init事件:页面初始化的标志是Init事件。页面中的控件(包括页面本身)都是在它们最初的Form中被首次初始化的。在成功创建页面的控件树后,对应用程序激发这个事件。当Init事件发生时,在.aspx源文件中静态声明的所有控件都以实例化并取其默认值。应该注意到,这是还没有视图状态信息可供使用。虽然可以重载OnInit方法,但是系统并不保证这些控件实例是按照怎样的顺序被创建的。

    2、加载视图:在初始化之后,页面框架立即加载该页面的视图状态(ViewState)。所谓视图状态就是一些名称/值对的集合,例如可以保存TextBox控件的ID和Text属性值。它一般被用于在一个往返行程中存留信息到服务器,即参与HTTP请求与响应。

    页面视图状态被存储在<input type=”hidden”>字段中,做为_VIEWSTAE的值进行记录。该视图状态通过ASP.NE自动维护。通过重写LoadViewState方法组件,开发人员可控制如何还原视图状态以及如何将其内容影射到内部状态。LoadViewState方法就是从ViewState中获取上一次的状态,并按照页面的控件树的结构,用递归来遍历整个树,将对应的状态恢复到每一个控件上。

    3、处理回发数据:还原了视图状态,页面树种的各个控件的状态就与浏览器上次呈现该页面时这些控件所处的状态相同。下一步需要更新这些控件的状态以发送给客户端。
    回发数据处理阶段是各个控件有机会更新其状态,以便准确的反映相应的HTML元素在客户端的状态。例如,一个服务器TextBox控件对应的HTML元素是<input type=text>,在回发数据阶段,TextBox控件将检索<input>标记的当前值并用它刷新其内部状态。每个控件负责从以发送的数据中提取相应值,并更新其某些属性。TextBox控件将更新Text属性,而CheckBox控件将刷新其Checked属性。服务器控件和HTML元素之间的匹配关系由二者的ID确定。

    页框架将在每个提交数据的控件上实现IpostBackDataHandler接口,然后激发LoadPostData事件,通过页面解析发现实现了IpostBackDataHandle接口的控件,这样就能正确的回传数据更新控件状态。在识别控件时,ASP.NET通过匹配控件的唯一标示符来更新正确的控件,该标识符具有名称值集和中的名称值对。这也就是在所有特定的页中每个控件都需要一个唯一标识符的原因之一。其他的步骤都由框架来完成,例如确定每个标识符在环境中是否唯一以及控件的基本属性等。

    LostPostData方法的原型如下:

    Public virtual bool LoadPostData(string postDatakey, NameValueCollection postCollection)

    PostDataKey是标识控件的关键字,可以理解为控件的ID,postCollection是包含回发数据的集合,可以理解为视图状态值。该方法返回一个bool值,如果是true,则表示控件状态因回发而更改;否则返回false。页框架会更跟踪所有返回true的控件并在这些控件上调用RaisePostDataChangeEvent事件。

    LoadPostData方法是由System..Web.WebControls.Control定义的,而添加的每一个服务器控件也是从System..Web.WebControls.Control继承的,所以对于数据的回发处理并不需要干预。

    4、加载页面Load:在回发数据处理阶段结束时,页面中的所有控件都根据客户端上所输入的更改来更新的状态。此时,对页面激发OnLoad事件。对于这个事件,相信大多数朋友都会比较熟悉,用Visual Studio.Net生成的页面中的Page_Load方法就是响应Load事件的方法,对于每一次请求,Load事件都会触发,Page_Load方法也就会执行。可以利用该方法执行一些页面初始化,例如准备好数据库的连接字符串。在事件引用中,为了提高性能,通常使用Page类的IsPostBack属性判断是不是数据回发。

    5、回发更改通知RaisePostDataChanged:如(3)所述,在所有实现了IpostBackDataHandler接口的控件被正确的回传数据更新后,每个控件都有一个布尔值的标识,标识其自上一次提交后改控件的数据是被更改还是保持其值。然后ASP.NET通过搜索页来寻找任何显示控件数据被更改的标识并激发RaisePostDataChanged。RaisePostDataChanged事件直到Load事件发生后,所有控件被更新后才激发。这保证了在控件被回传数据更新前,其他控件的数据在RaisePostDataChanged事件中没有被手动更改过。虽然也可以在Page的基础上自己定义数据更改的事件,但通常这个事件由太大用处。

    6、 处理回发事件RaisePostBackEvent:当回传更新导致数据改变而引发服务器端事件后,引发回传的对象会在RaisePostBackEvent事件中被处理。这种引发回传的对象往往是一个按钮被单击或者其状态改变而引发回传的控件。例如Button触发乐onclick事件、客户端修改了某个文本框的文本、同时将AutoPostBack设置为true、触发TextChanged事件等。

    很多代码都在这个事件中执行,因为这是控制事件驱动逻辑的理想位置。为了保证呈现到浏览器的数据的正确性,在一系列的回传事件后,RaisePostBackEvent事件最终被激发。基于一致性考虑,会传中改变的控件直到这个函数被执行后才被更新。在实际的ASP.NET开发工作中要做的工作就是在此事件发生前处理代码。

    7、预呈现PreRender:在处理回发事件后,页面就准备进行呈现。这一阶段的标志是PreRender事件。各个控件可利用这个很好的时机,以便执行任何需要在保存视图状态和呈现输出结果的前一刻完成得最后一些更新操作。最终请求的处理都会转变为发挥服务器的响应,预呈现这个阶段就是执行在最终呈现之前所做的状态的更改,因为在呈现一个控件之前,必须更具它的属性来产生HTML,比如Style属性。这是典型的例子,这预呈现之前,可以更改一个控件的Style,当执行预呈现时,就可以把Style保存下来,做为呈现阶段显示HTML的样式信息。

    8、保存状态SaveViewState:下一个状态为SaveViewState,在这一状态中所有控件以及页面本身可以刷新自己的SaveState集合的内容。所得到的视图状态随后得以序列化、进行哈希运算、进行Base64编码并关联到VI-EMSTATE隐藏自端。

    9、呈现视图Render:到这里,实际上页面对请求的处理基本就告一段落了,在Render事件中,也调用对象是它们呈现为HTML,然后也收集HTML发送给客户。客户接收到HTML标记后进行重组,最终显示给客户。当Render事件被重载时,开发者可以为浏览器创建定值的HTML,此时页面创建的任何HTML都还没有生效。Render方法用HtmlTextWriter对象做参数并由它产生HTML送给浏览器。这主要用于自定义控件的开发。

    10、处置Disposed:执行销毁控件前的所有最终清理操作。在此阶段必须释放对昂贵资源的引用,如内存的退出、数据库的连接等。

    11、卸载Unload:一个页面的最后生存标志就是Unload事件,该事件在页面对象被解除之前发生。在此事件中,可以调用Dispose方法尽可能释放占用的任何关键资源(例如,文件、图形对象以及数据库连接)。

    参考资料:
    http://www.cnblogs.com/framework/archive/2006/10/16/529835.html
    http://www.fiddlertool.com
    http://www.cnpaf.net/class/http/

    来源:http://www.cnblogs.com/nuaalfm

    2010年7月9日 8:03