本文來自《ASP.NET AJAX程式設計 第II卷:用戶端Microsoft AJAX Library相關》的第三章《非同步呼叫Web Service和頁面中的類方法》,請同時參考本章的其他文章。
3.5 非同步通訊層產生的用戶端代理類
在前面幾節中,我們已經看到了ASP.NET AJAX非同步通訊層為Web Service產生的用戶端非同步呼叫代理的基本使用方法。這裡有必要再詳細介紹一下該用戶端代理的功能,並做以總結。
如下代碼就是ASP.NET AJAX非同步通訊層為本章第1節中那個簡單的Web Service所產生的用戶端調用代理(代碼經過格式化):
var SimpleWebService = function() {
SimpleWebService.initializeBase(this);
this._timeout = 0;
this._userContext = null;
this._succeeded = null;
this._failed = null;
}
SimpleWebService.prototype = {
SayHello:
function(name,succeededCallback, failedCallback, userContext) {
return this._invoke(
SimpleWebService.get_path(),
'SayHello',
false,
{name:name},
succeededCallback,
failedCallback,
userContext
);
}
}
SimpleWebService.registerClass('SimpleWebService',Sys.Net.WebServiceProxy);
SimpleWebService._staticInstance = new SimpleWebService();
SimpleWebService.set_path = function(value) {
var e = Function._validateParams(arguments, [{name: 'path', type: String}]);
if (e)
throw e;
SimpleWebService._staticInstance._path = value;
}
SimpleWebService.get_path = function() {
return SimpleWebService._staticInstance._path;
}
SimpleWebService.set_timeout = function(value) {
var e = Function._validateParams(arguments, [{name: 'timeout', type: Number}]);
if (e)
throw e;
if (value < 0) {
throw Error.argumentOutOfRange('value', value, Sys.Res.invalidTimeout);
}
SimpleWebService._staticInstance._timeout = value;
}
SimpleWebService.get_timeout = function() {
return SimpleWebService._staticInstance._timeout;
}
SimpleWebService.set_defaultUserContext = function(value) {
SimpleWebService._staticInstance._userContext = value;
}
SimpleWebService.get_defaultUserContext = function() {
return SimpleWebService._staticInstance._userContext;
}
SimpleWebService.set_defaultSucceededCallback = function(value) {
var e = Function._validateParams(arguments, [{name: 'defaultSucceededCallback', type: Function}]);
if (e)
throw e;
SimpleWebService._staticInstance._succeeded = value;
}
SimpleWebService.get_defaultSucceededCallback = function() {
return SimpleWebService._staticInstance._succeeded;
}
SimpleWebService.set_defaultFailedCallback = function(value) {
var e = Function._validateParams(arguments, [{name: 'defaultFailedCallback', type: Function}]);
if (e)
throw e;
SimpleWebService._staticInstance._failed = value;
}
SimpleWebService.get_defaultFailedCallback = function() {
return SimpleWebService._staticInstance._failed;
}
SimpleWebService.set_path("/Chapter03/Services/SimpleWebService.asmx");
SimpleWebService.SayHello= function(name,onSuccess,onFailed,userContext) {
SimpleWebService._staticInstance.SayHello(name,onSuccess,onFailed,userContext);
}
可以看到,ASP.NET AJAX非同步通訊層為Web Service產生的用戶端非同步呼叫代理類各不相同,但均繼承於Sys.Net.WebServiceProxy類,以實現調用Web Service,而Sys.Net.WebServiceProxy類則又在內部使用Sys.Net.WebRequest組件完成實際的HTTP請求。
調用產生的Web Service用戶端代理中方法的文法如下:
[NameSpace].[ClassName].[MethodName](param1, param2 …, onSucceeded, onFailed, userContext)
我們也可以先建立一個Web Service用戶端代理的執行個體,然後用該執行個體調用Web Service的用戶端代理:
var myGenaratedWebServiceProxy = new [NameSpace].[ClassName]();
myGenaratedWebServiceProxy.[MethodName](param1, param2 …, onSucceeded, onFailed, userContext);
其中各個萬用字元以及參數的說明如表3-2所示。
表3-2 Web Service用戶端代理調用文法中的萬用字元和參數
- 萬用字元/參數:描述
- [NameSpace]:伺服器端Web Service的命名空間。若沒有顯式命名空間聲明,則該部分可以省略
- [ClassName]:伺服器端Web Service的類名
- [MethodName]:定義在伺服器端Web Service中的、將要被調用的方法名
- param1 param2 … param n:將要調用的方法的參數列表。其中參數的個數、順序要與Web Service中方法參數的定義嚴格保持一致
- onSucceeded:成功調用Web Service之後的回呼函數,該參數為可選
- onFailed:調用Web Service失敗時的回呼函數,該參數為可選
- userContext:調用Web Service時傳遞的使用者內容物件,該參數為可選
注意:對於onSucceeded、onFailed和userContext三個選擇性參數,若省略了位置靠前的某個參數而指定了靠後的參數,那麼一定要使用null佔位。例如,在發起某次調用時,我們希望跳過onFailed參數,並指定userContext,那麼調用文法將類似如下所示:
SomeNamespace.SomeClass.SomeMethod(param1, param2, onSucceeded, null, contextObj);
ASP.NET AJAX非同步通訊層為Web Service產生的用戶端代理組件還允許我們設定預設的onSucceeded、onFailed和userContext參數,分別通過set_defaultFailedCallback()、set_defaultFailedCallback()和set_defaultUserContext()方法完成。請參考如下代碼:
SomeNamespace.SomeClass.set_defaultSucceededCallback(defaultSucceededCallback);
SomeNamespace.SomeClass.set_defaultFailedCallback(defaultFailedCallback);
SomeNamespace.SomeClass.set_defaultUserContext("default context");
或者:
var theProxyInstance = new SomeNamespace.SomeClass();
theProxyInstance.set_defaultSucceededCallback(defaultSucceededCallback);
theProxyInstance.set_defaultFailedCallback(defaultFailedCallback);
theProxyInstance.set_defaultUserContext("default context");
設定了預設的回呼函數以及使用者內容物件之後,若調用時省略了某一項內容,則代理組件將自動選擇並使用預設的設定代替。若是調用時仍明確指定了某項內容,則該設定將覆蓋預設的設定。在實際開發中,合理地使用預設的onSucceeded、onFailed和userContext參數會極大地降低程式的代碼量,並讓程式邏輯更加清晰。
除此之外,ASP.NET AJAX非同步通訊層為Web Service產生的用戶端代理組件提供了逾時的配置:通過其set_timeout()方法,即可設定調用過程的最長等待時間(單位為毫秒)。請參考如下代碼:
SomeNamespace.SomeClass.set_timeout(3000);
或者:
var theProxyInstance = new SomeNamespace.SomeClass();
theProxyInstance.set_timeout(3000);
完整的成功回呼函數的簽名將類似如下所示:
function onSucceeded(result, userContext, methodName) {
// ......
}
其中result參數代表Web Service的傳回值;userContext參數代表使用者內容物件;methodName參數代表調用的Web Service方法的名稱。userContext和methodName參數均可在該回呼函數中提供一些關於原始調用者的額外資訊。
完整的失敗回呼函數的簽名將類似如下所示:
function onFailed(error, userContext, methodName){
// ......
}
其中error參數是一個Sys.Net.WebServiceError對象,代表導致本次非同步呼叫失敗的異常;userContext參數代表使用者內容物件;methodName參數代表調用的Web Service方法的名稱。其中userContext和methodName參數均可在該回呼函數中提供一些關於原始調用者的額外資訊。
提示:成功回呼函數和失敗回呼函數可以選擇任何的名字,並不限於書中提到的onSucceeded()和onFailed()。
3.6 使用HTTP GET進行調用
在使用ASP.NET AJAX非同步通訊層對Web Service進行非同步呼叫時,預設應用的是HTTP POST方式。但為了提供足夠的靈活性,ASP.NET AJAX非同步通訊層同樣允許我們使用HTTP GET進行調用。
使用HTTP GET進行調用時,方法的參數均被序列化成JSON字串,然後經過URL編碼並添加至URL後面送回給伺服器處理。關於GET和預設的POST方式的比較,在本卷第2章中已經有過詳細介紹,這裡不再重複。
若想以HTTP GET的方式對某個Web Service中的方法進行調用,那麼只要為該方法添加[ScriptMethod(UseHttpGet = true)]屬性即可。例如對於本章第1節中的樣本程式,我們可以按照如下代碼修改伺服器端Web Service中方法的定義,注意其中粗體部分:
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public string SayHelloUsingGET(string name)
{
return string.Format("Hello {0}!", name);
}
再次運行該樣本程式,並開啟HTTP嗅探器,可以看到本次非同步呼叫確實使用了HTTP GET。3-9所示。
圖3-9使用HTTP GET調用Web Service
注意:在使用HTTP GET請求Web Service時,特別要注意安全性問題。一般來講,只有在沒有暴露敏感資訊且沒有關鍵操作(例如刪除/更新資料)等安全的情況下,才可以使用HTTP GET。