頁(yè)面間傳遞數據的幾種方法 在頁(yè)面間傳遞數據時(shí),我們有以下幾種選擇:
1、Query String
一個(gè)很常見(jiàn)的方法,Query String是URL中問(wèn)號之后的那一部分。其優(yōu)點(diǎn)在于它是輕量級的,不會(huì )給服務(wù)器帶來(lái)任何負擔。而它也有幾個(gè)缺點(diǎn):傳遞的信息僅限于簡(jiǎn)單的字符串,而且必須是合法的URL字符;信息是對用戶(hù)是可見(jiàn)的,因而存在安全性問(wèn)題;用戶(hù)可能會(huì )嘗試手動(dòng)修改查詢(xún)字符串,這可能是程序未預料到或不能防范的;很多瀏覽器對URL的長(cháng)度都有所限制(通常為1KB到2KB)。
2、Cookie
Cookie是創(chuàng )建在客戶(hù)端硬盤(pán)上(或者,如果它們是臨時(shí)的,則在內存中)的小文件。其優(yōu)點(diǎn)在于使用時(shí)不易被用戶(hù)察覺(jué),可被程序中每個(gè)頁(yè)面使用,并且可將數據長(cháng)期保存。但它也有一些與Query String 相同的缺點(diǎn):僅限于簡(jiǎn)單的字符串信息;一旦用戶(hù)找到了相應的文件,它們也是易于訪(fǎng)問(wèn)和閱讀的。所以Cookie最好不要用于保存復雜的或私密的信息。
3、Session
可以在源頁(yè)面中將數據保存在Session中,然后在目標頁(yè)面中讀取這些數據。注意:將大量的信息存儲在Session中會(huì )嚴重影響服務(wù)器的性能。
4、Server.Transfer
要進(jìn)行服務(wù)器端的重定向,可以使用Server.Transfer。因為在服務(wù)器端執行,Server.Transfer方法不需要請求另一頁(yè)面。使用HttpContext,我們可以在目標頁(yè)面中訪(fǎng)問(wèn)源頁(yè)面中的數據。其缺點(diǎn)是,瀏覽器并不了解返回給它的是另外一個(gè)頁(yè)面,它在地址欄中會(huì )顯示第一個(gè)頁(yè)面的URL,這會(huì )讓用戶(hù)陷入混亂,在他們使用書(shū)簽的時(shí)候也會(huì )產(chǎn)生麻煩。所以不推薦該方法。
5、其它
還可以使用緩存(Cache)來(lái)存儲數據,可在程序的任意處訪(fǎng)問(wèn)緩存。建議僅對那些修改不太頻繁但經(jīng)常使用的數據使用緩存。 另外在某些特定情況下還可以使用Application變量,如統計頁(yè)面的點(diǎn)擊數等。
使用Cross-Page Postback ASP.NET 2.0中引入了一個(gè)新的方法:跨頁(yè)面提交,即postback觸發(fā)在另一個(gè)頁(yè)面。這種技術(shù)聽(tīng)起來(lái)很是簡(jiǎn)單,但卻存在隱患。一不小心,就會(huì )導致你創(chuàng )建的頁(yè)面緊密耦合,難以維護和調試。
支持跨頁(yè)面提交的機制是一個(gè)名為PostBackUrl的屬性,該屬性由IButtonControl接口定義,實(shí)現這個(gè)接口的按鈕控件包括ImageButton,LinkButton,Button。將PostBackUrl屬性值設置為另一個(gè)web窗體的名稱(chēng)(即URL),當用戶(hù)點(diǎn)擊按鈕時(shí),頁(yè)面將被提交到新的URL。
看下面這個(gè)示例,該示例包括源頁(yè)面CrossPage1.aspx和目標頁(yè)面CrossPage2.aspx:
CrossPage1.aspx
<html xmlns="http://www.w3.org/1999/xhtml" ><head runat="server"> <title>Source Page</title></head><body> <form id="form1" runat="server"> <div> FirstName: <asp:TextBox runat="server" ID="txtFirstName"></asp:TextBox> <br /> LastName: <asp:TextBox runat="server" ID="txtLastName"></asp:TextBox> <br /> <asp:Button runat="server" ID="cmdSubmit" PostBackUrl="~/CrossPage2.aspx" Text="Cross-Page Postback" /> </div> </form></body></html>
CrossPage1.aspx不包含任何代碼,效果如下:
現在點(diǎn)擊按鈕,該頁(yè)面就被提交到CrossPage2.aspx了。此時(shí)CrossPage2.aspx頁(yè)面可以使用Page.PreviousPage屬性與CrossPage1.aspx進(jìn)行交互了,下面這個(gè)事件處理函數演示了如何獲取源頁(yè)面的標題并顯示它:
if (PreviousPage != null){ lblInfo.Text = "You came from a page titled " + PreviousPage.Header.Title;} 注意:該方法在訪(fǎng)問(wèn)PreviousPage對象前先對其作了null檢查,如果結果為false,表明沒(méi)有跨頁(yè)面提交發(fā)生,也就是說(shuō),CrossPage2.aspx是被直接請求的,或者由其自身提交,此時(shí)PreviousPage對象不可用。
從源頁(yè)面中獲取更多數據 上面那個(gè)示例作了一個(gè)有趣的嘗試,但僅僅如此,我們還是不能傳遞任何有用的信息。
要獲取源頁(yè)面中控件的值,可以使用FindControl方法:
if (PreviousPage != null){ lblInfo.Text = "You came from a page title " + PreviousPage.Header.Title; string firstName = (PreviousPage.FindControl("txtFirstName") as TextBox).Text; string lastName = (PreviousPage.FindControl("txtLastName") as TextBox).Text; lblInfo.Text += "<br />"; lblInfo.Text += "your full name: " + firstName + " " + lastName;}要獲得更多信息,我們需要將PreviousPage引用轉換為適當的頁(yè)面類(lèi)(本示例中是CrossPage1類(lèi)):
if (PreviousPage != null){ CrossPage1 prevPage = PreviousPage as CrossPage1; if (prevPage != null) { // 此時(shí)可以訪(fǎng)問(wèn)源頁(yè)面的公共屬性 }}另外,除了在代碼中進(jìn)行類(lèi)型轉換,還可以在.aspx頁(yè)面中添加PreviousPageType指示字:
<%@ PreviousPageType VirtualPath="~/CrossPage1.aspx" %>
此時(shí),PreviousPage屬性會(huì )自動(dòng)使用CrossPage1類(lèi)型,編輯器中的智能提示也可以使用了。但是這種方法相當脆弱,因為你只能使用一個(gè)頁(yè)面類(lèi)!因此,出于靈活性考慮,使用類(lèi)型轉換的方法會(huì )更好。
好了,不管怎樣,現在已經(jīng)將PreviousPage對象轉換為合適的頁(yè)面類(lèi)型了,但是你還是不能直接訪(fǎng)問(wèn)它包含的控件對象。這是因為這些控件都被聲明為保護類(lèi)型(protected),此時(shí)的解決方案是使用屬性。
比如,如果希望公開(kāi)源頁(yè)面上兩個(gè)文本框控件的值,可以添加屬性來(lái)封裝控件對象,如在CrossPage1類(lèi)中添加屬性:
public TextBox FirstNameTextBox{ get { return txtFirstName; }}public TextBox LastNameTextBox{ get { return txtLastName; }}但是,這通常不是最好的方法。其問(wèn)題在于它公開(kāi)了太多的細節,目標頁(yè)面可以讀取文本框控件的所有內容了。如果過(guò)段時(shí)間需要修改源頁(yè)面,決定使用不同的輸入控件,維護這些屬性就相當困難了,因為你不得不修改兩個(gè)頁(yè)面的代碼。
更好的方法是定義更具體的屬性,它們應當僅僅提供你需要的東西。比如,你可以考慮添加一個(gè)FullName屬性,該屬性讀取兩個(gè)文本框的值:
public string FullName{ get { return this.txtFirstName.Text + " " + this.txtLastName.Text; }}這樣做,兩個(gè)頁(yè)面的關(guān)系就變得清晰、簡(jiǎn)單并易于維護了。如果你決定在CrossPage1中使用新的輸入控件,只要修改CrossPage1頁(yè)面就好了。CrossPage2中的代碼也相應地修改如下:
if (PreviousPage != null){ lblInfo.Text = "You came from a page titled " + PreviousPage.Header.Title + "<br />"; CrossPage1 prevPage = PreviousPage as CrossPage1; if (prevPage != null) { lblInfo.Text += "You typed in this: " + prevPage.FullName; }}下面是CrossPage2的最終結果:
跨頁(yè)面提交確實(shí)非常有用,但它們也會(huì )使頁(yè)面變得復雜。如果你允許多個(gè)源頁(yè)面提交到同一目標頁(yè)面,你就得編寫(xiě)代碼邏輯以判斷頁(yè)面來(lái)自何處,然后作出相應處理。要避免這種煩惱,簡(jiǎn)單的方法就是只在兩個(gè)特定的頁(yè)面間使用它。
By Anders Cui
參考:
Beginning.ASP.NET.2.0.in.C.Sharp.2005.From.Novice.to.Professional by Matthew MacDonald