首頁 >web前端 >js教程 >分享XmlHttpRequest呼叫Webservice的一點心得_javascript技巧

分享XmlHttpRequest呼叫Webservice的一點心得_javascript技巧

WBOY
WBOY原創
2016-05-16 17:51:321161瀏覽

首先,因為JSON對於JS的便利性,考慮透過JSON來請求和回傳資料。在JS中實例化一個xmlHttpRequest對象,然後根據網路上的說明POST的位址為:asmx頁面位址/Web方法名稱。在RequestHeader中設定Content-Type為application/json; charset=utf-8,SOAPAction設為Web方法名稱。 Web方法的參數用JSON格式send出去。
程式碼如下:

複製程式碼 程式碼如下:

function getXml 🎜>var xmlHttp;
if (window.XMLHttpRequest)
{ // code for IE7 , Firefox, Chrome, Opera, Safari
xmlHttp = new XMLHttpRequest();
}
🎜>{ // code for IE6, IE5
xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
}
return xmlHttp;
}
function webservice(url, action, data , success, error, complete, failed) {
var xmlHttp = getXmlHttp(); //取得XMLHttpRequest物件
xmlHttp.open('POST', url '/' action, true); //非同步請求資料
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4) {
try {
if (xmlHttp.status == 200 && typeof (success) == 'function' ) {
success(xmlHttp.responseText);
}
else if ((xmlHttp.status / 100 == 4 || xmlHttp.status / 100 == 5) && typeof (error) 100 == 5) && typeof (error) == ' function') {
error(xmlHttp.responseText, xmlHttp.status);
}
else if (xmlHttp.status / 100 == 200 && typeof (complete) == 'function') == ' >complete(xmlHttp.responseText, xmlHttp.status);
}
else if (typeof (failed) == 'function') {
failed(xmlHttp.responseText, xmlHttp.status) }
catch (e) {
}
}
}
xmlHttp.setRequestHeader('Content-Type', 'application/json; charset=utf-8') ;
xmlHttp.setRequestHeader('SOAPAction', action);
xmlHttp.send(data);
}


如要求呼叫Webservice1中的要求呼叫方法:

例如請求呼叫Webservice1中的要求要求呼叫:


複製程式碼 程式碼如下:
webservice('/Webservice1.asmx','Hello','{Hello'World }',function (msg) { alert(msg); });


呼叫前請記得把Webservice1上面的[System.Web.Script.Services.ScriptService] 取消註釋,呼叫後可以看到彈出警告視窗:{"d": "Hello World"}。把Content-Type設為text/xml時,警告視窗的內容變就變成了 Hello World
這時候雖然參數「{}」還是JSON的形式請求卻是XML格式,但因為Hello World沒有參數,所以忽略了內容的格式,能夠正常回傳值。
如果修改服務端的HelloWorld方法,新增一個string類型的參數somebody。


複製程式碼程式碼如下:
[WebMethod ) {
return "Hello World&Hello, " somebody "!";
}


將請求端的Content-Type改回application/json,傳送參數改為{"somebody": "Krime"},呼叫後彈出視窗內容變成{d: "Hello World&Hello, Krime!"}。
但如果這時再直接把Content-Type改為text/xml,呼叫後伺服器將會報錯:System.InvalidOperationException: 請求格式無效: text/xml; charset=UTF-8。 在System.Web.Services.Protocols.HttpServerProtocol.ReadParameters() 在System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
於是我們把參數格式也修改一下,按照Webservice頁面的範例,將參數改調試頁面的範例,將參數改調試為:



複製程式碼 程式碼如下:


Krime





這樣應該就能正常回傳XML的結果了吧?結果卻出乎意料,伺服器仍然回報同樣的錯誤。
折騰了很久後,幾乎要抓狂了,難道ASP.NET突然不認識XML了?這時候,再回去仔細看看Webservice調試頁面的範例,終於發現了一點問題:
複製程式碼 程式碼如下:

POST /WebServiceTest/Webservice1.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content>Content-Type: text/xml; charset=utf-8
Content-Length: length SOAPAction: "http://tempuri.org/HelloWorld"




string




上面POST的位址後面並沒有像請求JSON資料時一樣加上/方法名,而SOAPAction的方法名稱前面還需要加上命名空間。於是修改XMLHttpRequest的請求頭,url和action做相應修改,結果終於正常回傳了XML的結果:Hello World&Hello, Krime!:Envelope>
後來繼續測試,發現請求內容類型為application/json時,SOAPAction完全可以忽略不加,但是url後面一定要加上/方法名,否則伺服器不會回傳資料。而請求text/xml時,SOAPAction是必須的且前面要加上命名空間,url後面則不能有/方法名稱。
最後,經過總結,將程式碼改成了最終的樣子:
複製程式碼 程式碼如下:

function getXmlHttp() {
var xmlHttp;
if (window.XMLHttpRequest)
{ // code for IE7 , Firefox, Chrome, Opera, Safari
{ // code for IE7 , Firefox, Chrome, Opera, Safari. );
}
else
{ // code for IE6, IE5
xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
}
return xmlHttp;
function webservice(url, options) {
if (typeof (url) == 'object') { //將url寫在options裡的情況
options = url;
url = url .url;
}
if (!url) return;
if (options.dataType.toLowerCase() == 'json') { //請求JSON格式的資料時,url後面需要加上“/方法名稱”
url = url '/' options.method;
}
var xmlHttp = getXmlHttp(); //取得XMLHttpRequest物件
xmlHttp.open('POST', url,'POST', url, true); //非同步請求資料
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4) {
try {
if (xmlHttp.status == 200 &&& typeof (options.success) == 'function') {
options.success(xmlHttp.responseText);
}
else if ((xmlHttp.status / 100 == 4 || xmlHttp.status /Http. == 5) && typeof (options.error) == 'function') {
options.error(xmlHttp.responseText, xmlHttp.status);
}
else if (xmlHttp.status);
}
else if (xmlHttp.status) = = 200 && typeof (options.complete) == 'function') {
options.complete(xmlHttp.responseText, xmlHttp.status);
}
else if (type (options.failed) == 'function') {
options.failed(xmlHttp.responseText, xmlHttp.status);
}
}
catch (e) {
}
}
}
xmlHttp.setRequestHeader('Content-Type', options.contentType); //設定請求頭的ContentType
xmlHttp.setRequestHeader('SOAPAction', options.namespace options.method); //設定SOSOActionAP> xmlHttp.send(options.data); //傳送參數資料
}

請求JSON資料:
複製程式碼
複製程式碼


程式碼如下:


window.onload = function () {
var data = '{"somebody": "Krime"}';
var options = {
namespace: 'http://tempuri.org/',
method: 'HelloWorld',
contentType: 'application/json; charset=utf-8',
dataType: ' json',
data: data,
success: function (msg) {
alert(msg);
} }; webservice('http://localhost:8003 /WebServiceTest/Webservice1.asmx', options); };
請求XML資料:
複製程式碼 程式碼如下:
windowonload = function () {
var data = ''
''
''
''
'Krime'
'
'
''
'
';
var options = {
namespace: 'http://tempuri.org/',
method : 'HelloWorld',
contentType: 'text/xml; charset=utf-8',
dataType: 'xml',
data: data,
success: function (msg) {
alert(msg);
}
};
webservice('http://localhost:8003/WebServiceTest/Webservice1.asmx', options);
};


測試情況正常。
要注意的一點是,請求JSON資料時,如果回傳類型是DataTable是不行的,需要轉換成對應資料實體類別的List再回傳。

在解決回傳XML問題的過程中,也找到另一種解決方法。具體操作時,是將ContentType設為application/x-www-form-urlencoded,資料體不用JSON也不用XML格式的SOAP包,而是用類似QueryString的「arguement1=XXX&arguement2=XXX」。這個方法是模擬了窗體資料的HTTP POST格式,將每個控制項值編碼為名稱=值對傳送出去。

這種情況下的頁面位址後面也需要加上/方法名稱。
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn