在开发ASP.NET应用程序时,经常使用跨页面发布来传递页面数据。跨页面发布的优势在于,被传输的页面可以访问前一个页面以检索页面数据,这减少了会话管理的成本。因此,更倾向于使用跨页面发布。但是,跨页面发布有一个不喜欢的地方,那就是它不能在事件处理器中执行。当设置按钮的PostBackUrl属性以执行跨页面发布时,不幸的是,点击事件处理器不会工作。因此,如果想在事件处理器中执行某些操作后转移到另一个页面,不能使用跨页面发布。
因此,当使用跨页面发布时,必须使用几种实现技术。在某些情况下,必须设置PostBackUrl属性以执行跨页面发布。在其他情况下,必须实现一个事件处理器,以便在执行某些操作后使用Response.Redirect方法转移到另一个页面(尽管也可以使用HttpServerUtility.Transfer方法,但不想使用它)。此外,然后,必须使用会话或查询字符串将数据传递到另一个页面。
因此,页面传输和数据传递的实现变得复杂。为了减轻这种复杂性,想出了一种机制,可以在事件处理器中执行跨页面发布。它总是允许使用跨页面发布将数据传递到另一个页面。
想法的概念如图1所示。
图1. 想法的概念。
想法的主要点如下:
当异步回传完成时,将引发ScriptManager.endRequest事件。因此,此事件允许在客户端完成异步回传后执行额外的处理。
ClientScriptManager.GetPostBackEventReference方法允许在服务器端事件处理器中创建跨页面发布脚本。当传递一个适当设置的PostBackOption类的实例时,此方法会返回一个跨页面发布脚本作为字符串。
ScriptManger.RegisterDataItem方法可以用来将创建的脚本作为响应返回。此方法允许将任何数据存储在dataItems数组中。并且,dataItems数组可以在endRequest事件处理器中访问。
在endRequest事件处理器中,可以通过dataItems数组检索返回的跨页面发布脚本。当将脚本传递给eval方法时,将执行跨页面发布。
像普通的跨页面发布一样,可以使用PreviousPage属性从下一页访问前一页数据。自然地,PreviousPageType指令也有效。
以下是Page1.aspx的部分代码:
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="scriptManager" runat="server" />
<asp:UpdatePanel ID="updatePanel" runat="server">
<ContentTemplate>
<asp:Button ID="submitButton" runat="server" Text="Submit" OnClick="Submit" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
以下是Page1.aspx.cs的部分代码:
using System;
using System.Text;
using System.Web;
using System.Web.UI;
namespace SampleCode
{
public partial class Page1 : Page
{
public string OrderNo
{
get
{
return (string)ViewState["OrderNo"];
}
private set
{
ViewState["OrderNo"] = value;
}
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
StringBuilder script = new StringBuilder();
script.Append("var manager = Sys.WebForms.PageRequestManager.getInstance();");
script.Append("manager.add_endRequest(function(sender, args) {");
script.Append("if (args.get_error() == undefined) {");
script.Append("var dataItems = args.get_dataItems();");
script.Append("var item = dataItems['" + ClientID + "'];");
script.Append("if (item != undefined) {");
script.Append("eval(item);");
script.Append("}");
script.Append("}");
script.Append("});");
ClientScript.RegisterStartupScript(GetType(), "doCrossPagePostBack", script.ToString(), true);
}
protected void Submit(object sender, EventArgs e)
{
Random r = new Random();
OrderNo = String.Format("OD{0:00000000}", r.Next(0, 99999999));
NavigateTo("~/Page2.aspx");
}
private void NavigateTo(string url)
{
ScriptManager manager = ScriptManager.GetCurrent(this);
if (manager.IsInAsyncPostBack)
{
if (VirtualPathUtility.IsAbsolute(url) == false)
{
url = VirtualPathUtility.ToAbsolute(url);
}
PostBackOptions o = new PostBackOptions(this, String.Empty, url, false, false, false, true, false, String.Empty);
manager.RegisterDataItem(this, ClientScript.GetPostBackEventReference(o));
}
}
}
}
以下是Page2.aspx的部分代码:
<body>
<form id="form1" runat="server">
<asp:Label ID="orderNoLabel" runat="server" Text="Order No :" />
<asp:Label ID="orderNoValueLabel" runat="server" />
</form>
</body>
using System;
using System.Web.UI;
namespace SampleCode
{
public partial class Page2 : Page
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (PreviousPage != null && PreviousPage.IsCrossPagePostBack)
{
Page1 previousPage = (Page1)PreviousPage;
this.orderNoValueLabel.Text = previousPage.OrderNo;
}
}
}
}