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,却无论如何都无法将请求发出去了。
到底是什么原因使得跨页请求无法提交呢?大概和我们加入的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!

posted @ 2009-03-13 16:02  ST@N  阅读(1740)  评论(12编辑  收藏  举报