Cross-Page Postback 拾遗

ASP.NET 2.0中加入的Cross-Page Postback机制让我们ASP.NET开发人员有了轻松的(无需自定义)跨页面发POST请求的方式。但在实际开发时,难免遇到点小问题。比如在点击按钮发生跨页提交的时候,想先弹出一个JavaScript的confirm对话框进行确认,用户如果OK,发生postback,如果Cancel掉,就停留在原页面不做任何操作,类似于我们在删除按钮上添加的客户端功能。此时,便事不由人了……

我们准备两个页面。在Default.aspx中,加入文本框、按钮,设置按钮跨页回送到Target.aspx:
< asp:TextBox  ID ="TextBox1"  runat ="server" ></ asp:TextBox >
< asp:Button  ID ="Button1"  runat ="server"  Text ="Cross Page Post Back"  PostBackUrl ="~/Target.aspx"  OnClientClick ="return confirm('Are u sure?')"   />
在Target.aspx.cs中,Find到Default.aspx里的TextBox,把值显示在Label上:
protected   void  Page_Load( object  sender, EventArgs e)
{
    
if  (PreviousPage  !=   null )
        Label1.Text 
=  (PreviousPage.FindControl( " TextBox1 " as  TextBox).Text;
}
运行,然后发现当我们点击Cancel的时候,确实可以Cancel掉,但是点OK,却无论如何都无法将请求发出去了。
Cross-Page Postback 拾遗
到底是什么原因使得跨页请求无法提交呢?大概和我们加入的OnClientClick="return confirm('Are u sure?')"有关,因此我们查看一下浏览器里ASP.NET为了达到Cross-Page Postback效果而生成的源代码:
< input  name ="TextBox1"  type ="text"  id ="TextBox1"   />
< input  type ="submit"  name ="Button1"  value ="Cross Page Post Back"  onclick ="return confirm('Are u sure?');WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;Button1&quot;, &quot;&quot;, false, &quot;&quot;, &quot;Target.aspx&quot;, false, false))"  id ="Button1"   />

原来跨页回送依靠的是在submit之前,调用一个JavaScript的WebForm_DoPostBackWithOptions()函数,而我们所需要的return confirm()被加在了该函数调用的前面,因此,如果confirm()方法返回false,就return false了,不会有任何动作,而用户点OK按钮,confirm()返回true的话,相当于onclick="return true;",于是后面的WebForm_DoPostBackWithOptions()函数就无法调用了。

分析清楚了原因,再来找解决办法。在界面上弹出confirm对话框,必须用return cofirm()这一种方法么?既然confirm()方法的返回值是个bool类型,我们是否能把它放到if语句里呢?我们是否能把onclick里的调用改成if (confirm()) { doSomething(); }这种形式呢?

我们来改写按钮:
OnClientClick="if (confirm('Are u sure?')) "
测试后发现,点Cancel的时候却发生了Cross-Page Postback。
< input  name ="TextBox1"  type ="text"  id ="TextBox1"   />
< input  type ="submit"  name ="Button1"  value ="Cross Page Post Back"  onclick ="if (confirm('Are u sure?')) ;WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;Button1&quot;, &quot;&quot;, false, &quot;&quot;, &quot;Target.aspx&quot;, false, false))"  id ="Button1"   />
原因是ASP.NET会自动在我们的JavaScript语句后加上分号,所以,我们可以反过来写:
OnClientClick="if (confirm('Are u sure?')) return false;"
此时跨页回送完全可以达到我们的预期了。浏览器中生成的代码为:
< input  name ="TextBox1"  type ="text"  id ="TextBox1"   />
< input  type ="submit"  name ="Button1"  value ="Cross Page Post Back"  onclick ="if (!confirm('Are u sure?')) return false;WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;Button1&quot;, &quot;&quot;, false, &quot;&quot;, &quot;Target.aspx&quot;, false, false))"  id ="Button1"   />

以上,我们解决了在使用Cross-Page Postback机制时可能遇到的小问题。问题虽小,但想引起初学者注意的是解决问题的方法。编程经验从哪儿来呢?其实就是来自于解决问题的思路,而解决问题的思路又来自于对我们所储备知识的灵活应用。以上解决方案中涉及的知识点,大概作为初学者都已储备,剩下的其实就是需要我们在实际编程环境中通过思考、尝试,去积极寻找解决之道。在此借用一句烂俗的话:没有解决不了的问题。

接下去,我们是不是可以通过这种方式,自行去研究一下Cross-Page Postback的工作机制呢?这个在ASP.NET 1.1版没有,在2.0才加入的机制,是不是真有什么神奇之处呢?

首先,我们只看到了对WebForm_DoPostBackWithOptions()函数的调用,因此需要找到该函数的定义。通过查看客户端的源代码,我们并没有发现该函数的定义,但是找到了一个<script>标签,引用了一个外部的WebResource.axd文件:
< script  src ="/CrossPagePostBack/WebResource.axd?d=ZOvwxDkQx08x9P6zrcQviA2&amp;t=633694239333996679"  type ="text/javascript" ></ script >
我们将src中的虚拟路径粘贴到浏览器的地址栏,回车,浏览器会提示下载该WebResource.axd文件。将文件下载后,用文本文档打开。其中第一个function就是参数WebForm_PostBackOptions(),第二个function就是WebForm_DoPostBackWithOptions()了。我们可以看到WebForm_PostBackOptions()的第5个参数actionUrl,在被调用的时候用的是&quot;Target.aspx&quot;,也就是"Target.aspx",双引号被编码了而已。而WebForm_DoPostBackWithOptions对actionUrl做了些什么呢?
if  (( typeof (options.actionUrl)  !=   " undefined " &&  (options.actionUrl  !=   null &&  (options.actionUrl.length  >   0 )) {
    theForm.action 
=  options.actionUrl;
}

其实也就是将actionUrl设置给了表单(即<form name="form1" method="post" action="Default.aspx" id="form1">,在Default.aspx的客户端代码里可以找到var theForm = document.forms['form1'];)的action属性。这下就清楚了吧!ASP.NET的WebForm机制默认每个页面的表单数据以HTTP POST方法提交给页面自己(action="Default.aspx"为自动生成,自行修改也没用),称为Postback。而Cross-Page Postback,不就是允许将POST请求提交到别的action么!其本质也就是利用JavaScript,在submit之前(函数末尾调用了__doPostBack()函数)去修改表单元素的action属性。 

这下,对Cross-Page Postback机制是不是清楚了很多?顺着这样的思路,我们可以经常自己去分析一下ASP.NET Framework到底为我们准备好了哪些,它们是如何工作的,该如何让它们为我们所用,该如何去扩展改进它们,让它们更好的为我们工作。

 

Enjoy!

你可能感兴趣的:(post)