理解ASP.NET事件的工作原理

http://book.51cto.com/art/201201/312514.htm

ASP.NET如何将一个HTML按钮的单击转化为服务器的Click()事件呢?为了找到答案,必须检查一个包含有合适控件的ASP.NET页面。

程序清单2-4显示一个简单的Web页面,页面中有3个Label控件,分别是用来说明请求的类型(GET或POST)、用来判断此页面是否是PostBack的true或false标识(随后给出PostBack的解释)、一条消息(如果单击页面中的链接按钮时就出现此消息)。页面也会显示所发送的表单参数(如果有的话)。

程序清单2-4  含有按钮事件的ASP.NET页面

 
 
  1. <%@ Page Language="C#" %> 
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   
  3.       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
  4. <script runat="server"> 
  5.      protected void Page_Load(object sender, EventArgs e)  
  6.      {  
  7.          requestType.Text = Request.HttpMethod;  
  8.          cameFromPostBack.Text = Page.IsPostBack.ToString();  
  9.      }  
  10.      
  11.      protected void button_Clicked(object sender, EventArgs e)  
  12.      {  
  13.          message.Text = "You clicked the button";  
  14.      }  
  15.      
  16. </script> 
  17. <html xmlns="http://www.w3.org/1999/xhtml"> 
  18. <head runat="server"> 
  19.      <title>Postback Demo</title> 
  20. </head> 
  21. <body> 
  22.      <form id="form1" runat="server"> 
  23.      <div> 
  24.          Request Type: <asp:Label ID="requestType" runat="server"/><br /> 
  25.          IsPostback: <asp:Label ID="cameFromPostBack" runat="server"/><br /> 
  26.          <asp:Label ID="message" runat="server" /><br /> 
  27.          <asp:LinkButton ID="button" runat="server"   
  28.           OnClick="button_Clicked" Text="Click me!" />          
  29.      </div> 
  30.      </form> 
  31.       
  32.      <h3>Post Parameters</h3> 
  33.      <% foreach (string key in Request.Form.Keys)   
  34.          Response.Write(key + " = " + Request.Form[key] + "<br />");  
  35.      %>   
  36. </body> 
  37. </html> 

如果创建此页面并运行它,就可以在浏览器中查看页面源码(在页面中右击,如果是IE,就选择View Source命令;如果是Firefox浏览器,就选择View Page Source命令)。您会注意到,页面代码可能与您期望的不同。程序清单 2-5显示了此页面的HTML源码。

程序清单2-5  程序清单2-4中演示的页面的HTML源码

 
 
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   
  2.      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
  3.      
  4. <html xmlns="http://www.w3.org/1999/xhtml"> 
  5. <head><title> 
  6.      Postback Demo  
  7. </title></head> 
  8. <body> 
  9.     <form name="form1" method="post" action="PostbackDemo.aspx" id="form1"> 
  10. <div> 
  11. <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" /> 
  12. <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" /> 
  13. <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"   
  14.       value="/wEPDwUJMzYxMzIzNzk3D2QWAgIBD2QWBAIBDw8WAh4EVGV4d    
  15.       AUDR0VUZGQCAw8PFgIfAAUFRmFsc2VkZGTofcMG0NrB6D7A9nQm6it+z6YhSA==" /> 
  16. </div> 
  17.      
  18. <script type="text/javascript"> 
  19. //<![CDATA[  
  20. var theForm = document.forms['form1'];  
  21. if (!theForm) {  
  22.     theForm = document.form1;  
  23. }  
  24. function __doPostBack(eventTarget, eventArgument) {  
  25.     if (!theForm.onsubmit || (theForm.onsubmit() != false)) {  
  26.         theForm.__EVENTTARGET.value = eventTarget;  
  27.         theForm.__EVENTARGUMENT.value = eventArgument;  
  28.         theForm.submit();  
  29.     }  
  30. }  
  31. //]]> 
  32. </script> 
  33.     <div> 
  34.      <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION"   
  35.           value="/wEWAgKwgoeZCwLz9r7ABKfiEt1R2MFVeeJ0uDoFqNVcv8pj" /> 
  36.     </div> 
  37.     <div> 
  38.         Request Type: <span id="requestType">GET</span><br /> 
  39.         IsPostback: <span id="cameFromPostBack">False</span><br />      
  40.         <span id="message"></span><br /> 
  41.         <a id="button"   
  42.         href="javascript:__doPostBack('button','')">Click me!</a> 
  43.     </div> 
  44.     </form> 
  45.       
  46.     <h3>Post Parameters</h3> 
  47.           
  48. </body> 
  49. </html> 

此HTML源码包含几个感兴趣的地方。写本章内容时,在程序清单2-4中演示的页面被命名为PostbackDemo.aspx,本页面的HTML表单的action参数指回本页面。本页面中还有4个隐藏的表单域:_EVENTTARGET、_EVENTARGUMENT、_EVENTVALIDATION和_VIEWSTATE,还插入了一个用JavaScript编写的函数:_doPostBack()。最后,链接按钮已经作为<a>元素来呈现,并且具有一个客户端事件,用来调用插入的_doPostBack()函数。

当您仔细检查_doPostBack()函数时,会发现在此方法中,在调用表单的JavaScript submit()方法之前(submit()方法会导致浏览器提交包含这两个隐藏域的表单),首先设置两个隐藏域:_EVENTTARGET和_EVENTARGUMENT。

通过结合使用页面回发到自身(PostBack)和使用JavaScript设置事件源(和任意参数)这两种方式,允许ASP.NET实现事件模型。PostBack的生命周期如下:

(1) 第一次加载页面(通常是通过一个GET请求),ASP.NET创建Page对象和页面中所包含的所有控件。Page事件被触发,HTML被提交和返回到客户端。此时,释放Page对象(包括页面中所有的对象),最后,当.NET垃圾回收器运行时,所用的内存也被释放。

(2) 在客户端浏览器中,用户将执行一个创建PostBack的行为,如单击一个链接或按钮,或改变一个列表框选择项等。这些行为者中与客户端的JavaScript事件相联系,此事件将调用_doPostBack()方法,然后将本页面和表单数据提交到服务器。

(3)  ASP.NET创建一个新的page对象,并重新创建控件,当页面最后一次发送到客户端时,使用_VIEWSTATE域来设置对象的返回状态,并且运行页面初始化事件。

(4) 在_EVENTTARGET和_EVENTARGUMENT域设置结束后,ASP.NET使用EVENTVALIDATION域检查事件的有效性(例如,如果黑客通过隐藏的或不能使用的控件伪造了事件,就会发生异常)。然后ASP.NET使用_EVENTTARGET和_EVENTARGUMENT域决定触发哪一个服务器端的事件,然后引发该事件。在服务器端的事件代码中,页面通常以某种方式被修改(例如,计算一个新的价格或从数据库中检索信息)。

(5) 最后,将经过修改的页面呈现给HTML,并发送到客户端。Page对象(和那些页面元素成员)从内存中释放,如果此时有另外的PostBack发生,那么处理将从第(2)步重新开始。

如果对_EVENTVALIDATION和_VIEWSTATE域感兴趣,在第4章和第5章将有更详细的介绍。在整个生命周期中,触发很多事件用来构建页面,从ViewState重新创建控件内容,触发事件,最后呈现页面。如果您想看看页面生命周期中那些主要的事件,那么可以通过在页面声明中添加Trace="true"来启动跟踪,例如:

 
 
  1. <%@ Page Language="C#" Trace="true" % 

当启动跟踪时,调试信息也被添加到每一个页面中,如图2-8所示,显示了来自一个跟踪的事件信息示例。可以看到当加载完成页面后,处理回发事件。所以,在一个已经是产品的Web站点中从来也不要启用跟踪,否则,攻击者将很容易从跟踪数据中获取有关信息。
 
(点击查看大图)图2-8  事件跟踪数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值