ASP.NET用戶端回調代表著一種簡潔而絕佳的方法,它可以在不發布和重新整理當前頁的情況下執行伺服器端代碼。我在2004年8月和12月的CuttingEdge專欄中討論了ASP.NET回調,當時是從對伺服器進行後台回調、向相關頁發送輸入資料以及接收響應的呈現頁的角度對它們進行了討論。然後,響應字串由合適的用戶端進行處理,並且通常通過動態HTML(DHTML)物件模型和嵌入到頁面中的回調JavaScript函數來操作呈現的頁面內容。
儘管回調的這種用法已經讓人非常激動了,但它們還可以執行更多的任務。指令碼回調機制也可以為伺服器控制項添加進階功能。通過實現幾個介面,任何自訂控制項都會被賦予指令碼回調功能,以便使用後台往返來收集伺服器資料以及更新使用者介面—這就是本月我要講述的主題。
受GridView控制項的啟發
如果您讀過我最近寫的一篇功能文章ASP.NET2.0GridView,您就會瞭解GridView控制項無需重新整理整個頁面就可以顯示新的記錄頁。實際上,GridView控制項提供了一個基於ASP.NET指令碼回調進行分頁和排序的進階引擎。新頁面的資料是在後台下載的,使用者看不到。在資料到達用戶端之後,這些資料將立即由JavaScript函數收集,並用於更新當前視圖。
分頁和排序回調並不是100%的用戶端回調解決方案(如果您需要一個純粹的用戶端實現,請參閱2004年2月JeffProsise在WickedCode專欄中發表的文章)。GridView的分頁和排序回調是按需工作的,它只下載需要的資料,而不會將整個資料來源都下載到用戶端上。您仍然要付出一個往返的代價,但是能夠保證得到最新的資料,即使這些資料最近已經在伺服器上更新過。
自從發現ASP.NET控制項可以支援指令碼回調功能之後,我感到非常興奮,同時也促使我趕緊找出構建自己的指令碼回調的方法。
順便提一句,GridView並不是唯一一個支援類似功能的ASP.NET2.0控制項。其他視圖控制項(如TreeView、DetailsView和FormView)也能以其他方式提供相同的功能。作為使用具有回調功能控制項的開發人員,您不需要處理伺服器端代碼,也不用擔心編寫以及在宿首頁中嵌入JavaScript代碼的問題。該控制項可以完成一切操作,它展示了一個直觀的編程模型,您可以通過該模型控制指令碼回調機制。
控制項指令碼回調基本知識
ASP.NET指令碼回調機制由兩個關鍵元素組成:響應使用者操作的伺服器端代碼,以及用戶端上處理伺服器端事件所產生結果的JavaScript回調代碼。在頁面回調自身的情況下,正如我在前面提到的文章中所述的那樣,您可以在執行對使用者不可見的回傳的頁面按鈕中附加一些ASP.NET產生的指令碼代碼。因為該請求的目標是當前頁,所以該頁會發布到自身,這與它在一個普通回傳事件中的行為方式相似,只是頁面的生命週期縮短了。該頁必須實現ICallbackEventHandler介面,以便可以調用一個具有預定義簽名的方法,來為用戶端產生結果。
那麼,當控制項觸發帶外調用時,該方案又有什麼不同呢?在這種情況下,“不可見”回傳的目標URL是承載該調用方控制項的頁面的URL。該控制項必須實現ICallbackEventHandler才能提供為用戶端產生某些結果的方法。同樣,該控制項負責在承載頁中插入處理結果和重新整理該頁所需的任何JavaScript代碼。
具有回調功能的控制項只是一個實現ICallbackContainer和ICallbackEventHandler介面的控制項,兩個介面都各有一個方法。ICallbackContainer介面具有的方法可以返回觸發遠程調用的指令碼代碼;ICallbackEventHandler介面則提供了在調用期間執行的伺服器端代碼。ICallbackEventHandler也是一個具有回調功能的頁面必須實現的介面。一個實現回調介面的自訂控制項樣本的聲明如下面的代碼所示:
public class CallbackValidator : WebControl,
INamingContainer, ICallbackContainer, ICallbackEventHandler
在ICallbackContainer介面的實現中,您可能需要放入一個對該頁GetCallbackEventReference方法的調用,以獲得一個可啟動伺服器事件的正確JavaScript調用。稍後我再講述這些內容。