在ASP.ET 1.x的時候,很多朋友可能需要進行跨頁提交的處理,也就是從頁面A能夠提交到頁面B,甚至不同的Control其目標處理頁面也各不相同。尤其是從ASP/JSP/PHP轉過來的開發人員,可能更有這種需求。但很不幸,在ASP.NET 1.x的時候,處理這種跨頁請求是十分醜陋的,需要非常多的“技巧化”處理。
在ASP.NET 2.0的時候,對於跨頁提交已經有了非常合理的解決方案,以下就是一個樣本。
SourcePage.aspx: 請注意Button1的PostBackUrl屬性設定
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
public string YourName
{
get
{
return this.TextBox1.Text;
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" Text="請輸入您的姓名" Width="183px"></asp:Label>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="提交" PostBackUrl="~/TargetPage.aspx" /></div>
</form>
</body>
</html>
TargetPage.aspx:請注意PreviousPageType的屬性設定
<--<BR>
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->
<%@ Page Language="C#" %>
<%@ PreviousPageType VirtualPath="~/SourcePage.aspx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
this.Label1.Text = PreviousPage.YourName;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" ></asp:Label>
</div>
</form>
</body>
</html>
OK,就通過這麼簡單的兩個屬性設定,就可以非常方便的得到跨頁提交的特性。
讀取源頁面的資訊
ASP.NET 2.0中,Button控制項有個新增的屬性PostBackUrl,用來設定需要提交的目標頁面。因為只要指定Button控制項的PostBackUrl屬性就可以提交到其它頁面,我們可以在頁面中使用多個控制項配置其PostBackUrl的屬性,提交到不同的頁面。當然也可配置多個頁面提交到同一個頁面。
在跨頁面提交之後,通常我們需要從源頁面中讀取控制項的資訊(即由瀏覽器發送的資訊),以及源頁面的公用屬性。
讀取控制項的值
ASP.NET 2.0的Page類新增了一個PreviousPage屬性。顧名思義,目標頁面中的這個屬性包含對源頁面的引用。這樣就可以在目標頁面中通過PreviousPage屬性訪問源頁面的資訊,我們一般使用FindControl方法來尋找源頁面上的控制項並讀取這些控制項的值。下面的代碼說明了該方法的使用:
if (Page.PreviousPage != null)
{
TextBox txtName = (TextBox)Page.PreviousPage.FindControl("txtName");
if (txtName != null)
{
Label1.Text = txtName.Text;
}
}
當我們想尋找源頁面中控制項屬於另一個控制項或者是模板之中,就不能直接使用FindControl方法來讀取它,而是應該先擷取對該容器的引用,然後才能在該容器中尋找要擷取的控制項。下面的例子中,FirstPage.aspx頁面中包含一個Panel控制項,其ID為MainPanel,它還包含ID為UserName的TextBox控制項。具體代碼如下:
Panel MainPanel = (Panel)PreviousPage.FindControl("MainPanel");
if (MainPanel != null)
{
TextBox UserName = (TextBox)MainPanel.FindControl("UserName");
if (UserName != null)
{
Label1.Text = UserName.Text;
}
}
else
{
Label1.Text = "Cannot find UserName control.";
}
讀取源頁面的公用屬性
一旦在目標頁面中擷取了PreviousPage的引用,就能訪問源頁面中公用控制項的屬性,同樣也可訪問源頁面中的公用屬性。當然,我們需要預先在源頁面中公開需要被訪問的屬性方可在目標頁面中訪問。
若要擷取源頁面的公用成員,必須先擷取對源頁面的強型別引用。就像第一個例子中,我們可以使用@PreviousPageType指令來指定源頁面,它有兩個屬性分別為:VirtualPath和TypeName。使用VirtualPath屬性指定來源頁的虛擬路徑(包含檔案名稱),也可以使用TypeName指定源頁面的屬性。注意只能指定其中的一個,兩者都指定就會失效。如第一個例子中所示:
<%@ PreviousPageType VirtualPath="~/FirstPage.aspx" %>
如果使用了@PreviousPageType指令,目標頁面中的PreviousPage 屬性被強型別化為源頁面的類。因此,可以直接引用源頁面的公用成員。要擷取對源頁面的強型別引用的另一種方法是在目標頁面中包含一個@Reference 指令,就像引用要在頁面中使用的其它任何類型一樣。在這種情況下,你可以在目標頁面中擷取目標頁面的PreviousPage屬性並將其強制轉換為源頁面的類型,如下面的代碼所示:
SourcePage_aspx sourcePage;
sourcePage = (SourcePage_aspx) PreviousPage;
Label1.Text = sourcePage.UserName;
讀取源頁面中的Form資訊
如果源頁面和目標頁面屬於同一個 ASP.NET 應用程式,則目標頁中的PreviousPage屬性包含對源頁面的引用。在沒有使用@PreviousPageType指令的情況下,目標頁面中PreviousPage 屬性類型化為Page。
注意,如果該頁不是跨頁發送的目標頁面或者目標頁面位於不同的應用程式中,則不會初始化PreviousPage屬性。
如果源頁面和目標頁面屬於不同的應用程式,甚至是不同的網站,那就無法直接擷取源頁面上控制項的值,但可以從Request.Form中讀取發送的資料。還有一個需要注意的問題,因為源頁面的檢視狀態經過Hash處理,所以不能從源頁面中閱讀檢視狀態。如果要在源頁面中儲存值並讓這些值可供其他應用程式中的目標頁使用,可以將這些值作為字串儲存在源頁面的隱藏欄位中,並在目標頁面中通過 Request.Form 來訪問它們。
判斷是否為跨頁面提交
跨頁面提交的時候,源頁面控制項的內容被提交到目標頁面,然後瀏覽器執行POST操作(注意,不是GET)。在ASP.NET 1.x中由於頁面都是自己提交給自己,可以通過Page的IsPostBack屬性來判斷是否為頁面提交。但是在跨頁面提交的時候,目標頁面的IsPostBack屬性為false。如果要判斷是否為跨頁面提交,可以對目標頁面的PreviousPage屬性返回的引用頁面的IsCrossPagePostBack屬性進行判斷,如下面的代碼所示:
if(PreviousPage != null)
{
if(PreviousPage.IsCrossPagePostBack == true)
{
Label1.Text = "跨頁面提交";
}
}
else
{
Label1.Text = "非跨頁面提交";
}
注意,如果當前頁面不是跨頁面提交的目標頁面,則其PreviousPage屬性為空白。
跨頁面提交 VS Server.Transfer
ASP.NET 2.0中,無論是跨頁面提交還是使用Server.Transfer操作,都可以使用Previousoage屬性來擷取對源頁面的引用。如果要區分它們,可以使用上面介紹的方法。
下面是跨頁面提交與Server.Transfer之間的一些區別:
屬 性
跨頁面提交
Server.Transfer
IsPostBack
false
false
PreviousPage
源頁面的引用
源頁面的引用
PreviousPage.IsCrossPagePostBack
true
false
IsCrossPagePostBack
false
false
IsCallBack
false
false
跨頁面提交是用戶端瀏覽器的行為,而Server.Transfer則是伺服器端的行為。在後面的小節中,我們會分析跨頁面提交時用戶端瀏覽器是如何?提交的。
對跨頁面提交的簡單分析
在上面的例子中,我們都提到設定Button的PostBackUrl屬性來實現跨頁面提交。其實只要實現IButtonControl介面的控制項均可以實現這一點。Button, ImageButton, 和 LinkButton都實現了IButtonControl介面。通過實現IButtonControl,自訂控制項也可以有表單中的按鈕所具有的跨頁面提交的功能。IButtonControl介面彙總了ASP.NET 1.x支援的多數按鈕控制項(包括一些html按鈕控制項)的一些屬性。
讀取源頁面的資訊
ASP.NET 2.0中,Button控制項有個新增的屬性PostBackUrl,用來設定需要提交的目標頁面。因為只要指定Button控制項的PostBackUrl屬性就可以提交到其它頁面,我們可以在頁面中使用多個控制項配置其PostBackUrl的屬性,提交到不同的頁面。當然也可配置多個頁面提交到同一個頁面。
在跨頁面提交之後,通常我們需要從源頁面中讀取控制項的資訊(即由瀏覽器發送的資訊),以及源頁面的公用屬性。
讀取控制項的值
ASP.NET 2.0的Page類新增了一個PreviousPage屬性。顧名思義,目標頁面中的這個屬性包含對源頁面的引用。這樣就可以在目標頁面中通過PreviousPage屬性訪問源頁面的資訊,我們一般使用FindControl方法來尋找源頁面上的控制項並讀取這些控制項的值。下面的代碼說明了該方法的使用:
if (Page.PreviousPage != null)
{
TextBox txtName = (TextBox)Page.PreviousPage.FindControl("txtName");
if (txtName != null)
{
Label1.Text = txtName.Text;
}
}
當我們想尋找源頁面中控制項屬於另一個控制項或者是模板之中,就不能直接使用FindControl方法來讀取它,而是應該先擷取對該容器的引用,然後才能在該容器中尋找要擷取的控制項。下面的例子中,FirstPage.aspx頁面中包含一個Panel控制項,其ID為MainPanel,它還包含ID為UserName的TextBox控制項。具體代碼如下:
Panel MainPanel = (Panel)PreviousPage.FindControl("MainPanel");
if (MainPanel != null)
{
TextBox UserName = (TextBox)MainPanel.FindControl("UserName");
if (UserName != null)
{
Label1.Text = UserName.Text;
}
}
else
{
Label1.Text = "Cannot find UserName control.";
}
讀取源頁面的公用屬性
一旦在目標頁面中擷取了PreviousPage的引用,就能訪問源頁面中公用控制項的屬性,同樣也可訪問源頁面中的公用屬性。當然,我們需要預先在源頁面中公開需要被訪問的屬性方可在目標頁面中訪問。
若要擷取源頁面的公用成員,必須先擷取對源頁面的強型別引用。就像第一個例子中,我們可以使用@PreviousPageType指令來指定源頁面,它有兩個屬性分別為:VirtualPath和TypeName。使用VirtualPath屬性指定來源頁的虛擬路徑(包含檔案名稱),也可以使用TypeName指定源頁面的屬性。注意只能指定其中的一個,兩者都指定就會失效。如第一個例子中所示:
<%@ PreviousPageType VirtualPath="~/FirstPage.aspx" %>
如果使用了@PreviousPageType指令,目標頁面中的PreviousPage 屬性被強型別化為源頁面的類。因此,可以直接引用源頁面的公用成員。要擷取對源頁面的強型別引用的另一種方法是在目標頁面中包含一個@Reference 指令,就像引用要在頁面中使用的其它任何類型一樣。在這種情況下,你可以在目標頁面中擷取目標頁面的PreviousPage屬性並將其強制轉換為源頁面的類型,如下面的代碼所示:
SourcePage_aspx sourcePage;
sourcePage = (SourcePage_aspx) PreviousPage;
Label1.Text = sourcePage.UserName;
讀取源頁面中的Form資訊
如果源頁面和目標頁面屬於同一個 ASP.NET 應用程式,則目標頁中的PreviousPage屬性包含對源頁面的引用。在沒有使用@PreviousPageType指令的情況下,目標頁面中PreviousPage 屬性類型化為Page。
注意,如果該頁不是跨頁發送的目標頁面或者目標頁面位於不同的應用程式中,則不會初始化PreviousPage屬性。
如果源頁面和目標頁面屬於不同的應用程式,甚至是不同的網站,那就無法直接擷取源頁面上控制項的值,但可以從Request.Form中讀取發送的資料。還有一個需要注意的問題,因為源頁面的檢視狀態經過Hash處理,所以不能從源頁面中閱讀檢視狀態。如果要在源頁面中儲存值並讓這些值可供其他應用程式中的目標頁使用,可以將這些值作為字串儲存在源頁面的隱藏欄位中,並在目標頁面中通過 Request.Form 來訪問它們。
該文章轉載自網路大本營:http://www.xrss.cn/Dev/DotNet/200752313471.Html