回調(diào)等。
網(wǎng)上關(guān)于ASP.NET2.0 Callback的介紹已經(jīng)很多了,但是全面系統(tǒng)講述并帶有示例的還比已經(jīng)系統(tǒng)講述較少。正好這幾天在研究SharpMap的AjaxMap控件,就搜集和整理了這方面的資料。為了方便大家的學搜集大家為了習,同時節(jié)省大家搜集和閱讀資料的時間,我就寫了這篇搜集閱讀節(jié)省博文,希望不是畫蛇添足,呵呵。其中可能會摘引一些其畫蛇添足希望一些它文章的段落(稱為“雜文”^-^),在此表示感謝,如果作者覺得我侵犯了版權(quán),請聯(lián)系表示聯(lián)系版權(quán)我修改刪除。
1 Postback VS Callback
1.1 ASP.NET1.1中的Postback機制
在asp.net1.1中,我們知道每個服務(wù)器控件都有一個AutoPostback屬性。它的作用是當用戶(客戶端)修改該控件的值,即用戶客戶作用也可以說是當該控件的事件觸發(fā)的時候,客戶端就通過JavaScript:__doPostback(object,EventArgument)來和服務(wù)端實現(xiàn)通信。它使得程序員在實現(xiàn)動態(tài)的獲取服程序員實現(xiàn)獲取務(wù)端數(shù)據(jù)變得非常方便。例如:有一個查詢成績的頁面,成績例如查詢由一個DrowDownlist和一個DataGrid來實現(xiàn)。其中DropDownlist從服務(wù)綁定所要查看的學期(2003-2004上半學期,2003-2004下半學期等),DataGrid而是用來顯示他在改學期所有科目的成績,和該學科的學成績顯示而是分。在ASP.NET1.1中我們最常使用的方法也就是將DrowDownlist的AutoPostback屬性設(shè)置為True,并把該事件觸發(fā)服務(wù)端后臺的某個方法,該方法獲取所事件方法獲取選擇的學期的id號,然后去數(shù)據(jù)庫獲得DataTable重新綁定與DataGrid并將它顯示出來。在這整個過程中,作為用戶肯定是要經(jīng)顯示出來用戶歷一個刷新頁面的過程。如果僅像剛才那個例子所說這個刷新剛才頁面刷新不會很大的影響用戶的Experience,不過如果你有一個復(fù)雜的填寫表單的頁面,該頁面有大不過頁面復(fù)雜量的Control是相關(guān)的,需要更據(jù)其它Control的選擇情況去動態(tài)的綁定數(shù)據(jù),那當用戶填完這個表單的數(shù)據(jù)動態(tài)情況時候也許眼睛也花了,他也許再也不想經(jīng)歷如此痛苦的折再也眼睛也許磨了,從Experience方面來講將是非常差的。在不是從服務(wù)端獲取大量數(shù)據(jù)的獲取非常數(shù)據(jù)情況下,我們要如何才能避免這種在用戶看似多余的Postback呢?
1.2 ASP.NET2.0中新功能Script Callback介紹
在ASP.NET2.0中,客戶端的腳本功能已經(jīng)被擴展了。并且增加了Script Callbacks(通過腳本建立于后臺的鏈接,后文將其翻譯為客戶端呼翻譯腳本建立叫)。你可以用程序去控制<head>標簽,通過程序控制input焦點,讀取或者設(shè)置頁面的標題,并且可以控制button或其他的控件提交到其他任何頁面(in the application)。具體您可以查看Beta 1說明,里面有例子和參考。
為了使用ASP.NET2.0中的客戶端呼叫技術(shù),你需要在頁面中定義一個觸發(fā)元件技術(shù)定義觸發(fā)(不是提交按鈕Submit button)并且把它綁定上JavaScript代碼。這段代碼會重新獲得當前頁面的input數(shù)據(jù)并且準備去呼叫系統(tǒng)提供的一個稱為WebForm_DoCallback的Script函數(shù)(Beta1)。這個函數(shù)會建立一個和一個指定的遠程ASP.NET頁面建立HTTP連接。后臺偵聽到這個來自客戶端的呼叫后呢,對此觸發(fā)來自觸發(fā)連接一個方法。服務(wù)端通過先前的客戶端的函數(shù)返回一個值。方法函數(shù)客戶在客戶端,通過一個用戶自定義的腳本函數(shù)來獲得服務(wù)端定義腳本函數(shù)的值并且用DHTML將其呈現(xiàn)在頁面上。重要的是,這樣做客戶端和服務(wù)端的這樣頁面客戶通信仍舊在進行,但是頁面并沒有重新刷新。更重要的是刷新進行仍舊,當客戶端在獲取數(shù)據(jù)的時候用戶仍舊可以在它原來的頁可以仍舊獲取面上操作。
2 Callback VS Atlas
我們再來談?wù)凙tlas。很多朋友可能會覺得奇怪,已經(jīng)有Callback,為什么又要出Atlas呢?關(guān)于這個問題,Atlas的作者怎么解釋,我倒沒有去調(diào)查。只不過從我個人對callback和atlas的使用感受來講,覺得,callback作為一個接口和postback非常類似的實現(xiàn),肯定是為了讓用戶類似使用postback來使用它。但是,它的這個類似postback的機制,應(yīng)該說使用上還不是特別方便,也不易擴展,當應(yīng)該特別使用然這是相比于其他的AJAX框架實現(xiàn)來說的。因此,微軟方面借鑒了許多的已有的AJAX實現(xiàn),如Prototype,Backbase以及AJAX.NET,并結(jié)合ASP.NET2.0的部分特有功能,發(fā)明了這樣一個博采眾長的AJAX框架。基于Atlas來開發(fā)AJAX應(yīng)用有多好,很難量化的來說,但至少不比其他的這些AJAX框架來的差是肯定的,加上微軟這個后臺,以及像live.com這樣的重量級站點的應(yīng)用推廣,其影響當然是值得期待的重量級這樣應(yīng)用。
不過,這也不是說Callback實現(xiàn)沒一無是處了,作為程序員,我們需要有正確的態(tài)度一無是處態(tài)度我們,在正確的使用情形,使用最正確的技術(shù)。沒有哪一個框技術(shù)沒有情形架是萬能的,是適合任何使用環(huán)境的;就像大家都在爭論環(huán)境爭論適合那個軟件開發(fā)方法最好,CMMi,RUP,XP,AGILE~~,其實,沒有最好,最合適的才是最好的。我們最應(yīng)該做應(yīng)該我們沒有的,是了解各種方案的原理和優(yōu)缺點,從而,合理的使用方案各種原理正確的工具來解決實際問題。Callback的好處就是簡單,在Asp.net 2.0不需要額外的支持。
3 Callback原理
Callback可以翻譯成“客戶端回調(diào)”。在期望不執(zhí)行Postback而從客戶端調(diào)用服務(wù)器代碼的情況下,可以使用ClientScriptManager類來調(diào)用客戶端回調(diào)。這稱為對服務(wù)器執(zhí)行帶外回調(diào)。在服務(wù)器執(zhí)行調(diào)用客戶端回調(diào)中,客戶端腳本函數(shù)向ASP.NET網(wǎng)頁發(fā)送異步請求。網(wǎng)頁修改其正常生命周期來處理回調(diào)請求正常異步。
回調(diào)的過程如下所示:
1)客戶端發(fā)出請求,請求內(nèi)容包括:指定更新控件和傳遞請求包括內(nèi)容參數(shù)。
2)服務(wù)端響應(yīng)、處理。
3)服務(wù)端將處理后的內(nèi)容以字符串返回。
4)客戶端使用一個函數(shù)接受返回值
5)客戶端更新指定控件。
創(chuàng)建實現(xiàn)客戶端回調(diào)的ASP.NET頁,必須實現(xiàn)ICallbackEventHandler接口。
先聲明該接口,方法如下:
public partial class CallBackExample
: System.Web.UI.Page,System.Web.UI.ICallbackEventHandler
{… …}
實現(xiàn)ICallbackEventHandler接口的兩個固定名稱的方法,RaiseCallbackEvent(eventArgment)和GetCallbackResult()。RaiseCallbackEvent()方法是回調(diào)執(zhí)行的方法,在這個方法中處理回調(diào)的內(nèi)容,內(nèi)容方法執(zhí)行它沒有返回值,它從瀏覽器接受一個字符串作為事件參數(shù)瀏覽器字符串參數(shù),即該方法接受客戶端JavaScript使傳遞的參數(shù),注意它是首先觸發(fā)的。接下來觸發(fā)的就是接下來參數(shù)注意GetCallbackResult()方法,它將所得到的結(jié)果傳回給客戶端的JavaScript,JavaScript再將結(jié)果更新到頁面。
客戶端使用ClientScript.GetCallbackEventReference()方法實現(xiàn)回調(diào)。這個方法用幾個參數(shù)其中一個指定關(guān)聯(lián)上參數(shù)關(guān)聯(lián)方法下文,一個指定返回客戶端的函數(shù)名稱。
Public string GetCallbackEventReference (Control control,string argument,string clientCallback,string context)
參數(shù)與返回值說明:
參數(shù)
作用
control
處理客戶端回調(diào)的服務(wù)器Control。該控件必須實現(xiàn)ICallbackEventHandler接口并提供RaiseCallbackEvent方法。
argument
從客戶端腳本傳遞一個參數(shù)到服務(wù)器端的RaiseCallbackEvent方法。
clientCallback
一個客戶端事件處理程序的名稱,該處理程序接收服務(wù)器服務(wù)器事件程序端事件返回的結(jié)果。
context
啟動回調(diào)之前在客戶端的客戶端腳本信息。腳本的結(jié)果傳腳本結(jié)果客戶回給客戶端事件處理程序。
返回值
調(diào)用客戶端回調(diào)的客戶端函數(shù)的名稱。
注意:ClientScript.GetCallbackEventReference()方法在客戶端必須有控件來調(diào)用,調(diào)用的控件不是我們經(jīng)方法我們調(diào)用常使用的服務(wù)器端控件,而是一個HTML元素。在控件中添加一個onclick事件,點擊該按鈕這將向服務(wù)器端發(fā)出回調(diào)請求。
下面是ClientScriptManager.GetCallbackEventReference方法的重載列表
名稱
說明
ClientScriptManager.GetCallbackEventReference (Control, String, String, String)
獲取一個對客戶端函數(shù)的引用;調(diào)用該函數(shù)時,將啟動一調(diào)用函數(shù)獲取個對服務(wù)器端事件的客戶端回調(diào)。此重載方法的客戶端函服務(wù)器事件方法數(shù)包含指定的控件、參數(shù)、客戶端腳本和上下文。
ClientScriptManager.GetCallbackEventReference (Control, String, String, String, Boolean)
獲取一個對客戶端函數(shù)的引用;調(diào)用該函數(shù)時,將啟動一調(diào)用函數(shù)獲取個對服務(wù)器端事件的客戶端回調(diào)。此重載方法的客戶端函服務(wù)器事件方法數(shù)包含指定的控件、參數(shù)、客戶端腳本、上下文和布爾值上下文參數(shù)腳本。
ClientScriptManager.GetCallbackEventReference (Control, String, String, String, String, Boolean)
獲取一個對客戶端函數(shù)的引用;調(diào)用該函數(shù)時,將啟動一調(diào)用函數(shù)獲取個對服務(wù)器端事件的客戶端回調(diào)。此重載方法的客戶端函服務(wù)器事件方法數(shù)包含指定的控件、參數(shù)、客戶端腳本、上下文、錯誤處上下文參數(shù)錯誤理程序和布爾值。
ClientScriptManager.GetCallbackEventReference (String, String, String, String, String, Boolean)
獲取一個對客戶端函數(shù)的引用;調(diào)用該函數(shù)時,將啟動一調(diào)用函數(shù)獲取個對服務(wù)器端事件的客戶端回調(diào)。此重載方法的客戶端函服務(wù)器事件方法數(shù)包含指定的目標、參數(shù)、客戶端腳本、上下文、錯誤處上下文參數(shù)錯誤理程序和布爾值。我們就整個程序作個系統(tǒng)的說明,并且列出前臺的頁面代列出說明系統(tǒng)碼和后臺的邏輯代碼,這樣可以使得你對程序有個直觀的可以代碼程序理解。
4 示例
在后臺寫個public string,在Page_Load中給他賦值為:=Page.ClientScript.GetCallbackEventReference(this, "message"clientscript messag string;, "ShowServerTime", "context");注意在這里是Page.ClientScrip,因為他會返回個ClientScriptManager,ClientScriptManager管理showservertim clientscrip context所有的客戶端腳本。然后在前臺某個按鈕的onclick事件里<%=那onclick 事件腳本個public后臺字符串%>.做個小實驗代碼如下:
前臺ServerTime.aspx:為了方便去掉好多沒用的html
<%@ page language="C#" CodeFile="ServerTime.aspx.cs" Inherits="ServerTime_aspx" %>
<html>
<head>
<title>Server Time</title>
<script language="javascript">
function GetServerTime()
{
var message = '';
var context = '';
<%=sCallBackFunctionInvocation%>
}
function ShowServerTime(timeMessage, context) {
alert('現(xiàn)在服務(wù)器上的時間是:\n' timeMessage);
}
</script>
</head>
<body>
<form id="MainForm" runat="server">
<input type="button" value="得到服務(wù)器端時間" onclick="GetServerTime();" />
</form>
</body>
</html>
后臺:
using System;
using System.Web.UI;
public partial class ServerTime_aspx : Page,ICallbackEventHandler
{
//一定要實現(xiàn)ICallbackEventHandler借口
public string sCallBackFunctionInvocation;
void Page_Load(object sender, System.EventArgs e)
{
sCallBackFunctionInvocation = Page.ClientScript.GetCallbackEventReference(this, "message", "ShowServerTime", "context");
}
public string RaiseCallbackEvent(string eventArgument)
{
return DateTime.Now.ToString();
}
}