實現一個Asp.net自訂Back控制項
最後更新:2017-02-28
來源:互聯網
上載者:User
asp.net|控制項 本文講述了如何給Web頁面添加一個伺服器端控制項,從而將使用者的瀏覽器重新導向到該控制項所指向的頁面(referring page)。
by Juval Lowy
Q:實現一個ASP.NET Back控制項
我想在ASP.NET頁面中添加一個連結,通過它,我可以返回到它所指向的頁面。不知怎樣用一個伺服器端控制項來實現它呢?我想通過該控制項返回到已訪問過的頁面,而並不想用瀏覽歷程記錄的方法。
A:
你可以用兩種方法在一個Web頁面上實現一個“Back”連結。第一種方法是用用戶端指令碼讀取前面已訪問過的頁面的記錄,並將它重新導向到前一個頁面:
<a href= "javascript:history.back()">Back</a>
不過這種方法有幾個缺點。應用程式不能控制使用者被重新導向到了哪裡。通常情況下,你總是想讓使用者留在應用程式內,而不想讓他們跑到其它頁面。只有當瀏覽器支援用戶端指令碼時,這種方法才可行。其最大的缺點就是它與ASP.NET編程模式不一致。ASP.NET的一個最大的好處就是它不同於傳統的ASP,它不需要你依賴於用戶端指令碼。你只需要知道如何使用你用Managed 程式碼寫的伺服器端控制項就行了,ASP.NET會為你完成其它的工作。在使用用戶端指令碼時,Back連結與應用程式的其它部分是沒有關係的,它是在伺服器上啟動並執行,並運用了伺服器端的控制項。這會使你很難控制是否啟用Back連結,而且你也很難控制重新導向,因為它們都是以伺服器端事件處理常式為基礎的。
第二種方法是用一個ASP.NET自訂的使用者控制項。本文所附帶的源檔案在WebControlsEx類庫程式集中包含一個BackLink ASP.NET使用者控制項。如果要用該控制項,你需要右擊Web Forms工具箱,從彈出的操作功能表中選擇Add/Remove Items。點擊.NET Frameworks Components Tab鍵並按Browse按鈕。選擇WebControlsEx程式集,點Open。這樣就在toolbox上添加了BackLink使用者控制項。你只需要將它拖放到你的form中,就可以添加一個連結式的控制項了,其text屬性是“Back”。在設計時,該控制項具有與標準的連結按鈕一樣的屬性,如連結樣式(見圖1)。當使用者在運行時點擊該按鈕時,它會將瀏覽器引導到前一個頁面(如果有的話)。
實現BackLink使用者控制項並不像我們所看到的那麼簡單。要構建一個Web使用者控制項,你必須用DLL類庫。你可以通過兩種方法來提供一個使用者控制項:繼承一個叫做WebControl的類並對它進行自訂,或繼承一個現有的控制項並進行自訂。對於BackLink控制項來說,目前一個比較好的方法就是繼承一個LinkButton,因為LinkButton控制項提供了大部分很難實現的功能。
你可以從LinkButton繼承一個叫做BackLink的類,在它的構造器中將Text屬性設定為Back,並提供一些有意義的預設值:
public class BackLink : LinkButton
{
public BackLink()
{
Text = "Back";
}
}
實際上,繼承一個LinkButton在HTML中可以體現出來。通過繼承BackLink,該控制項在設計器中可以體現LinkButton所有的屬性——如預設的屬性、字型設定屬性和事件。
LinkButton有一個叫做OnClick()的受保護的虛擬方法,當返回頁面時,.NET會調用該方法,讓連結按鈕觸發點擊事件。LinkButton必須覆蓋OnClick()並將使用者重新導向到控制項所指向的頁面。
重要的問題是在BackLink控制項範圍內,如何在伺服器端得到當前頁面所指向的頁面。幸運的是,ASP.NET具有這樣的功能:HttpRequest對象提供了一個Url類型的公開的屬性,稱為UrlReferrer,它表示的是所指向頁面的URL。LinkButton使用者控制項可以得到對頁面的引用,這是通過Control類的Page屬性實現的。Control是WebControl的基類,WebControl是LinkButton的基類。該控制項也可以用Page屬性來讀取其HttpResponse對象(Response屬性),從而將使用者重新導向到所指向的頁面。
然而,如果你用下面的代碼來實現BackLink控制項,那麼該連結會不起作用:public class BackLink : LinkButton
{
public BackLink()
{
Text = "Back";
}
protected override void
OnClick(EventArgs e)
{
Uri backURL =
Page.Request.UrlReferrer;
Page.Response.Redirect(
backURL.AbsoluteUri);
}
}
原因在於ASP.NET跟蹤所指向頁面的方式。例如,我們以Home.aspx頁面為例,它會將使用者引導到SubForm.aspx頁面。如果SubForm.aspx頁面有一個BackLink控制項,使用者點擊該連結後,就會觸發返回頁面到伺服器的事件。伺服器上UrlReferrer屬性的值是“SubForm.aspx”(而不是“Home.aspx”),因為當返回頁面時,SubForm.aspx指向的是它自己。解決方案就是在載入控制項時,在session變數中緩衝所指向的頁面,並在OnClick()中重新導向到所指向的頁面。
現在,你還需要解決幾個問題:ASP.NET並不是總能提供具有導向資訊的頁面的,在這種情況下,ASP.NET將UrlReferrer的值設定為空白。你也需要提供一個“智能的”Back連結,它可以重新導向到邏輯上的前一個頁面。換句話說,如果一個包含BackLink的頁面自己重載(在處理了一些控制項的點擊事件後),Back連結應該可以很“聰明”地檢測到這一點,並重新導向到“真實”的前一個頁面,而不是它本身。注意,如果你用用戶端代碼,這是不可能實現的,因為在再次載入時,Back記錄變數會呈現同樣的頁面。
BackLink覆蓋了其基類的OnLoad()方法(見列表1)。當載入包含BackLink控制項的頁面時,調用OnLoad()。OnLoad()首先查看是否有所指向的頁面資訊。如果UrlReferrer是空的,那麼OnLoad()就會讓Back連結不起作用。如果有導向資訊,你需要驗證所指向的頁面不是當前頁面。你可以通過比較所指向頁面的URL和請求頁面的URL來實現這一點:
if(backURL.AbsolutePath != Page.Request.Url.AbsolutePath)
如果兩個URL不一樣,BackLink就把所指向頁面的URL儲存在一個session變數中:
Page.Session["Referring URL"] = backURL;
然後它會啟用該控制項。如果地址是一樣的,BackLink在啟用控制項前,需要驗證所指向頁面的URL是否已經緩衝過了。在OnClick()中,你必須讀取session變數,如果session變數存在,就將使用者重新導向到控制項指向的頁面。
你也可以在可視化設計頁面上設計使用者控制項。當你將控制項拖放到Web form時,ToolboxData屬性會告訴VS.NET在ASPX檔案中插入什麼。ToolboxBitmap包含對控制項表徵圖的一個引用(以嵌入資源的形式)。如圖1所示,一旦你添加了控制項,表徵圖就會顯示在toolbox中。
原始碼:
[ToolboxData("<{0}:BackLink runat=server></{0}:BackLink>")]
[ToolboxBitmap(typeof(BackLink),"BackLink.bmp")]
public class BackLink : LinkButton
{
public BackLink()
{
Text = "Back";
ToolTip =
"Click to go to the previous page";
}
protected override void OnClick(EventArgs e)
{
Uri backURL = (Uri)Page.Session[
"Referring URL"];
Page.Session["Referring URL"] = null;
if(backURL != null)
{
Page.Response.Redirect(
backURL.AbsoluteUri);
}
}
protected override void OnLoad(EventArgs e)
{
Uri backURL = Page.Request.UrlReferrer;
if(backURL == null) //No referrer
information
{
Enabled = false;
return;
}
if(backURL.AbsolutePath !=
Page.Request.Url.AbsolutePath)
{
Page.Session["Referring URL"] =
backURL;
Enabled = true;
return;
}
else
{
object obj = Page.Session[
"Referring URL"];
if(obj != null)
{
Enabled = true;
}
}
base.OnLoad(e);
}
}