默认情况下,在 ASP.NET 网页中引起回发的按钮和其他控件将页提交回该页本身。这是 ASP.NET 网页在其正常的处理过程中所要经历的往返周期的一部分。在某些情况下,可能需要将一个页发送到其他页。例如,您可能正在创建一个收集每个页上不同信息的多页窗体。在此情况下,可以将页中的某些控件(实现 IButtonControl 接口的控件,如 Button 控件)配置为发送至不同的目标页。这被称为跨页发送。跨页发送与使用 Transfer 方法重定向到其他页相比,具有一些优点。
从源页获取信息
为跨页发送配置页时,您通常需要从源页中获取信息。这可能包括来自页上控件的信息(即由浏览器发送的信息),以及源页的公共属性。
获取控件值
Page类公开一个名为PreviousPage的属性。如果源页和目标页位于同一 ASP.NET 应用程序中,则目标页中的PreviousPage属性包含对源页的引用。(如果该页不是跨页发送的目标或者这些页位于不同的应用程序中,则不会初始化PreviousPage属性。) 默认情况下,PreviousPage属性类型化为Page。
如果源页和目标页位于不同的应用程序中,则无法直接获取页上控件的值,但可以从 Form 字典中读取发送的数据。因为源页经过散列处理,所以不能从源页中读取视图状态。如果要在源页中存储值并使这些值可供其他应用程序中的目标页使用,则可以将这些值作为字符串存储在源页的隐藏字段中,并在目标页中通过 Request.Form 来访问它们。
在 PreviousPage 属性中使用引用,便可以搜索源页上的控件并提取这些控件的值。通常使用 FindControl 方法来执行此操作。
if (Page.PreviousPage != null)
{
TextBox SourceTextBox =
(TextBox)Page.PreviousPage.FindControl("TextBox1");
if (SourceTextBox != null)
{
Label1.Text = SourceTextBox.Text;
}
}
FindControl 方法在当前的命名容器中查找控件。如果要查找的控件位于另一控件内(通常位于模板内),则必须先获取对该容器的引用,然后才能在该容器中查找要获取的控件。在下面的代码示例中,源页包含一个 Login 控件,并具有一个 LayoutTemplate 容器,而该容器又包含一个名为 UserName 的 TextBox 控件。该代码获取 UserName 控件的值。
Login LoginControl = (Login)PreviousPage.FindControl("Login1");
if (LoginControl != null)
{
TextBox UserName = (TextBox)LoginControl.FindControl("UserName");
if (UserName != null)
{
Label1.Text = UserName.Text;
}
}
else
{
Label1.Text = "Cannot find user name in Login control.";
}
从源页获取公共属性值
在跨页发送的目标页中,也可以获取源页的公共成员的值。最常见的方案是源页定义公共属性,并且您要在目标页上获取这些属性的值。
建议您只将需要的信息作为公共属性公开,以减少可能被潜在的恶意用户使用的信息量。
若要获取源页的公共成员,必须先获取对源页的强类型引用。
可以通过多种方法来执行此操作。第一种方法是在目标页中包含一个@ PreviousPageType指令,该指令允许您指定源页,如此示例中所示:
<%@ PreviousPageType VirtualPath="~/SourcePage.aspx" %>
包含此指令时,PreviousPage 属性被强类型化为被引用的源页的类。因此,可以直接引用源页的公共成员。可以使用 type 属性直接指定源页的类型,也可以通过在 VirtualPath 属性中显式引用源页来间接指定源页的类型,如该示例中所示
下面的代码示例演示源页的一部分,其中包含一个名为 CurrentCity 的公共属性,该属性用于公开名为 textCity的 TextBox 控件的值。
public String CurrentCity
{
get
{
return textCity.Text;
}
}
在源页上创建的、主要用于为跨页发送公开值的属性通常是只读属性。尽管源页可以包含公共读/写属性,但是通过目标页属性设置源页属性一般没有任何效果,因为不会保留此值。
如果目标页中包含指向源页的 PreviousPageType 指令,则可以使用下面的代码访问源页的 CurrentCity 属性。
Label1.Text = PreviousPage.CurrentCity;
获取对源页的强类型引用的另一种方法是在引用源页的目标页中包含一个@ Reference指令,正如引用要在页中使用的任何类型一样。在此情况下,您可以在目标页中获取目标页的PreviousPage属性并将其强制转换为源页类型,如下面的代码示例所示。
SourcePage_aspx sourcePage;
sourcePage = (SourcePage_aspx) PreviousPage;
Label1.Text = sourcePage.CurrentCity;
@ Reference的用法例子下载
检查目标页中的回发
在跨页回发过程中,源页控件的内容被发送至目标页,并且浏览器执行 HTTP POST 操作(不是 GET 操作)。但在目标页中,在跨页发送之后,IsPostBack属性便立即成为 false。尽管该行为是 POST 的行为,但跨页发送并不是到目标页的回发。因此,IsPostBack 设置为 false,并且目标页可以通过它的第一次代码。
如果这在您的应用程序中有用,则可以确定目标页是否由于跨页发送而正在运行。为此,您可以对目标页的PreviousPage属性返回的页引用的IsCrossPagePostBack属性进行测试,如下面的代码示例所示。
if(PreviousPage != null)
{
if(PreviousPage.IsCrossPagePostBack == true)
{
Label1.Text = "Cross-page post.";
}
}
else
{
Label1.Text = "Not a cross-page post.";
}
请注意,如果当前页不是跨页发送的目标,则 PreviousPage 属性返回 null(在 Visual Basic 中为 Nothing)。
跨页发送与 Server.Transfer
PreviousPage属性和 PreviousPageType 指令在调用目标页的两种情况下都很有用:在跨页回发中(这是一种基于客户端的传输)和使用Transfer 方法时(这是基于服务器的操作)。在以上两种操作中,目标页中的代码都可以使用PreviousPage 属性获取对源页的引用。
在目标页中,确定页是通过跨页发送还是 Server.Transfer 操作调用可能很重要。为了帮助您执行此操作,Page 类公开了一个名为IsCrossPagePostBack 的属性