ASP.NET 2.0 CallBack機制撰寫AJAX程式
在ASP.NET 2.0中提供有別於PostBack的CallBack功能,它讓我們可以在ASP.NET 2.0上撰寫AJAX程式,要在ASP.NET 2.0上撰寫CallBack程式,要先了解 ICallbackEventHandler這個Interface,該Interface有兩個方法:GetCallbackResult ()、RaiseCallbackEvent(ByVal eventArgument As String),所以我們可介由繼承ICallbackEventHandler這個Interface並且實作這兩個方法,來完成CallBack機制撰寫AJAX程式,以下是我們Sever-Side的完整程式碼:
程式八:小工具CallBack程式Sever-Side程式碼 |
Partial Class ThsrcDB Inherits System.Web.UI.Page Implements System.Web.UI.ICallbackEventHandler Dim rtnTime As String '要回傳的時刻字串 Dim rtnPrice As String '要回傳的票價字串 Public Function GetCallbackResult() As String Implements System.Web.UI.ICallbackEventHandler.GetCallbackResult Return rtnTime & "^" & rtnPrice'時刻字串與票價字串由『^』分隔,查詢後傳回Client-Side End Function 'eventArgument由Client-Side傳入 Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent Dim A() As String A = eventArgument.Split("^") Dim SSiteID As String = A(0) Dim ESiteID As String = A(1) Dim SSiteTime As String = A(2) Dim ESiteTime As String = A(3) Dim SEType As String = A(4) rtnTime = GetTimeData(SSiteID, ESiteID, SSiteTime, ESiteTime, SEType) rtnPrice = GetPriceData(SSiteID, ESiteID) End Sub Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim cbReference As String '建立 Call back程式碼-指定回傳函式為 ReceiveServerData Dim strArg As String = "" strArg &= "document.all." + ddlTimeFrom.ClientID + ".value +'^'" strArg &= "+document.all." + ddlTimeTo.ClientID + ".value +'^'" strArg &= "+document.all." + ddlSTime.ClientID + ".value +'^'" strArg &= "+document.all." + ddlETime.ClientID + ".value +'^'" strArg &= "+document.all." + ddlSE.ClientID + ".value" cbReference = Page.ClientScript.GetCallbackEventReference(Me, strArg, "ReceiveServerData", "") '註冊 btnSearch.Attributes("onclick") = cbReference '設計一個函式(名稱為ReceiveServerData),接收 Server 端 Call Back 回來的值 Dim ReceiverScript As String = "" ReceiverScript += vbCrLf + "<script>" ReceiverScript += vbCrLf + " function ReceiveServerData(DataFromServer)" ReceiverScript += vbCrLf + "{" ReceiverScript += vbCrLf + "var a=DataFromServer.split('^');" ReceiverScript += vbCrLf + "document.all.divTime.innerHTML=a[0];" ReceiverScript += vbCrLf + "document.all.divPrice.innerHTML=a[1];" ReceiverScript += vbCrLf + "document.all.fdsResult.style.display ='block';" ReceiverScript += vbCrLf + "document.all.imglodaing.style.display ='none';" ReceiverScript += vbCrLf + "}" ReceiverScript += vbCrLf + "</script>" '在頁面上註冊(寫入)這個函式 Page.ClientScript.RegisterClientScriptBlock(GetType(String), "ReceiverScript", ReceiverScript) End Sub Function GetTimeData(ByVal SSiteID As String, ByVal ESiteID As String, ByVal SSiteTime As String, ByVal ESiteTime As String, ByVal SEType As String) As String Dim sp As New StringBuilder Dim dv As DataView With Me.sqldsTime .SelectParameters(0).DefaultValue = SSiteID .SelectParameters(1).DefaultValue = ESiteID .SelectParameters(2).DefaultValue = SSiteTime .SelectParameters(3).DefaultValue = ESiteTime .SelectParameters(4).DefaultValue = SEType dv = .Select(New DataSourceSelectArguments) End With For Each dr As DataRowView In dv If CType(dr(2), String) <> "" Then sp.Append(String.Format("<span style='color: red' alt='車次:{0}({1}行駛)' altbg='red' altcolor='yellow' altborder=yellow>{2}</span>、", dr(0), dr(2), dr(1))) Else sp.Append(String.Format("<span alt='車次:{0}'>{1}</span>、", dr(0), dr(1))) End If Next If sp.ToString = "" Then Return "" Else Return sp.ToString.Substring(0, sp.ToString.Length - 1) End If End Function Function GetPriceData(ByVal SSiteID As String, ByVal ESiteID As String) As String Dim sp As New StringBuilder Dim dv As DataView With Me.sqldsPrice .SelectParameters(0).DefaultValue = SSiteID .SelectParameters(1).DefaultValue = ESiteID dv = .Select(New DataSourceSelectArguments) End With For Each dr As DataRowView In dv sp.Append(String.Format("●【{0}】:{1}元<br>", GetTypeStr(dr(0)), CType(dr(1), String).PadLeft(10, " "))) Next If sp.ToString = "" Then Return "" Else Return sp.ToString.Substring(0, sp.ToString.Length - 4) End If End Function Function GetTypeStr(ByVal str As String) As String Dim RTN As String = "" Select Case str Case "0" RTN = "標準車廂-全票" Case "1" RTN = "商務車廂-全票" Case "2" RTN = "標準車廂-優待票" Case "3" RTN = "商務車廂-優待票" Case "4" RTN = "自由座-全票" Case "5" RTN = "自由座-優待票" Case "6" RTN = "標準車廂-團體票" Case "7" RTN = "商務車廂-團體票" End Select Return RTN.PadRight(8, " ") End Function End Class |
運作流程如下:在Page_Load事件中指定會觸發CallBack物件與事件(btnSearch物件的onclick事件),且該CallBack會傳送什麼前端資訊(strArg)至伺服器端,同時指定伺服端執行完成後會呼叫前端ReceiveServerData函式;該函式為CallBack程式碼指定回傳函式,接收 Server端 Call Back 回來的值,且將該函式註冊寫入在前端頁面上,而程式碼中會將從伺服器端接收回來的DataFromServer參數分割再放入對應呈現時刻(divTime)與票價(divPrice)的物件中。
而實作ICallbackEventHandler的GetCallbackResult方法是伺服端傳給客戶端資料,它會對應至前面所述的ReceiveServerData函式中的DataFromServer參數;而實作ICallbackEventHandler的RaiseCallbackEvent方法,其中eventArgument是由客戶端傳入,亦就是前面所說的strArg參數,因為該客戶端傳入的參數只有一個,固我們利用組字串時加入『^』來分隔,在伺服端再以^來分割成各變數,再透過切割後的變數,傳入GetTimeData、GetPriceData兩個方法,分別呼叫GetTime與GetPrice預存程序來取得時刻與票價相關資料,整個完成後,即會觸發ICallbackEventHandler的GetCallbackResult方法將存放時刻rtnTime與票價rtnPrice的字串組合後傳至前端ReceiveServerData函式中的DataFromServer參數。
將AJAX程式包裹成Web Gadget
至此我們完成小工具資料庫的設計、高鐵資料的取得、UrMap地圖的套用、AJAX程式的撰寫,它是個完整獨立的網頁小程式,在Microsof的Web Gadgets與Google的Universal Gadgets都提供單獨網頁嵌入Gadget小工具的方式,在實作Microsof的Web Gadgets的包裹作法前,需先了解一個基本的Gadget包含下面4個檔案:
- Gadget Manifest(配置檔;附檔名:xml):必要檔案,其檔案採用XML結構的形式,檔案裡定義一些屬性與指定所參考的Gadget JavaScript與Gadget Style Sheet和圖檔檔案的位置。
- Gadget JavaScript(邏輯程式檔;附檔名:js):必要檔案,這個檔案包含一些邏輯程式碼、屬性與定義 Gadget該如何動作。
- Gadget Style Sheet(樣式表;附檔名:css):非必要檔案,該CSS檔案為該Gadget的樣式檔,設定它如何呈現外觀與介面。
- Gadget 圖檔(附檔名:jpg或png):非必要檔案,指定該Gadget的圖示。
本範例的Gadget Manifest配置檔如下,指定它的標題、說明與所參考的Gadget JavaScript(gadget.js)和它的圖示(pic.jpg),要特別注意的是binding:type要與Gadget JavaScript內的建構元件對應起來。
程式九:小工具的Gadget Manifest(gadget.xml) |
<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" xmlns:binding="http://www.live.com"> <channel> <title>台灣高鐵乘車資訊全方位指南</title> <description>提供台灣高鐵乘車資訊全方位指南,除可查各站點之票價、時間、轉乘、訂票資訊與週遭景點資訊外且結合UrMap地圖可友善設定啟到站與查啟到站時間。</description> <language>zh-tw</language> <binding:type>MLChen.Spaces.Gadget.TaiwanThsrc</binding:type> <item> <link>gadget.js</link> </item> <icons> <icon height="32" width="32">pic.jpg</icon> </icons> </channel> </rss> |
至於Gadget JavaScript程式碼如下,除了名稱空間與建構式等要特別注意外,在單獨網頁嵌入Gadget小工具中僅要將url網址改成您所要嵌入Gadget小工具的單獨網頁即可,而其它只要將所屬的Gadget檔案,本例中的gadget.xml、gadget.js、pic.jpg壓成一個壓縮檔zip,接著即可至http://gallery.live.com,將辛苦製作的小工具上傳至 Windows Live Gallery透過Gadget的方式分享給大家。
程式十:小工具的Gadget JavaScript |
// 註冊小工具的名稱空間 (namespace) registerNamespace("MLChen.Spaces.Gadget"); //// 定義此小工具的建構元 。 //(名稱必須相同於清單檔(XML)的設定)。 MLChen.Spaces.Gadget.TaiwanThsrc = function(p_elSource, p_args, p_namespace) { // 做任何事之前必須先呼叫 initializeBase 函式。 MLChen.Spaces.Gadget.TaiwanThsrc.initializeBase(this, arguments); // 設定一些私有成員變數 (private member variables)。 var m_el = p_elSource; var m_module = p_args.module; /**************************************** ** initialize Method (初始化方法) ****************************************/ // 當你的物件開始執行時,這個 initialize 函式會永遠立即被呼叫。 this.initialize = function(p_objScope) { // 總是先呼叫 Base 物件的 initialize 函式。 MLChen.Spaces.Gadget.TaiwanThsrc.getBaseMethod(this, "initialize", "Web.Bindings.Base").call(this, p_objScope); // 小工具背景透明化 。 if (window.parent != window.self) { document.body.style.backgroundColor = "transparent"; } var url ="http://www.abc.com.tw/Thsrc.aspx"; m_el.innerHTML = "<iframe src=\"" + url + "\" frameborder=\"0\" scrolling=\"auto\" height=\"500\" width=\"466\"/>" }; MLChen.Spaces.Gadget.TaiwanThsrc.registerBaseMethod(this, "initialize"); /**************************************** ** dispose Method (解除方法) ****************************************/ this.dispose = function(p_blnUnload) { // 清除所有的成員變數 m_this = null; m_el = null; m_module = null; // 最後總是呼叫 base 物件的 dispose 函式 MLChen.Spaces.Gadget.TaiwanThsrc.getBaseMethod(this, "dispose", "Web.Bindings.Base").call(this, p_blnUnload); }; MLChen.Spaces.Gadget.TaiwanThsrc.registerBaseMethod(this, "dispose"); }; MLChen.Spaces.Gadget.TaiwanThsrc.registerClass("MLChen.Spaces.Gadget.TaiwanThsrc", "Web.Bindings.Base"); |
總結:
網路邁入Web 2.0的時代,有別於Web 1.0網友僅能單項接收資訊或服務,此處我們借由Microsoft或Google提供的平台,依各平台規格撰寫服務或小工具程式,即可提供我們開發的服務給其它人使用,而該台灣高鐵乘車資訊全方位指南小工具又以混搭(mashup)的方式,使用到地圖供應商UrMap提供的地圖服務,且查詢方式又以AJAX方式呈現,豐富使用者體驗,故我們慢慢可以了解Yahoo!奇摩總經理鄒開蓮表示:『小工具正是Web 2.0精神的展現』這句話的意思。
這篇Gadget小工具設計實務是以筆者參加台灣微軟所主辦、捨得資訊協辦的2007 Windows Live Spaces Gadgets部落格小工具設計大賽的佳作作品,唯筆者在看這場競賽時,實覺十分可惜,在一再強調使用者體驗(User Experience)的Gadget小工具上,反諷的是協辦單位所開發舉辦Gadget競賽活動平台竟沒有讓筆者有絲毫感到使用者體驗的部分,光作品需上傳至Windows Live Gallery外還要再上傳一次至競賽網站這一點筆者就十分不能理解,更不用說該競賽平台竟有一堆Bug,反應協辦單位後亦沒有多大改善,或許這只是個小活動、小競賽,無須太過認真,但如此就會失去辦這活動的意義了。
參考資料:
| |
| |
| |
| |
| |
| 台灣高鐵官方網站 |
相關連結:
| 台灣高鐵乘車資訊全方位指南Gadget小工具位址:http://gallery.live.com/LiveItemDetail.aspx?li= |
| 台灣高鐵乘車資訊全方位指南Gadget小工具使用簡報: http://cid-f315ca8945fc |