使用 Microsoft 登入
登入或建立帳戶。
您好:
選取其他帳戶。
您有多個帳戶
選擇您要用來登入的帳戶。

ASP.NET 支援語音欄

使用 XMLHTTP 的動態頁面更新

若要根據您的需求自訂此欄,我們想要在您感興趣的主題中提交您的想法,並提供您想要在未來的知識庫文章中,以及支援語音欄的問題。 您可以使用 [ 要求 It ] 表單提交您的想法和意見反應。 此欄底部的表單也有一個連結。

簡介

研究 Web 應用程式可用性的我最愛的方式之一,就是觀察我的妻子流覽網站。 她可以在網際網路上輕鬆地完成,但她幾乎對低級技術方面的瞭解, (她會撥打「令人厭煩的東西」 ) ,讓它全部正常運作。



在最近的一天,我正在觀看妻子 peruse 來自其中一個大型 boys 的電子商務應用程式。 她使用多重下拉式清單來向下切入產品清單,每個下拉式清單則是從先前所做的選取範圍中寄出。 當她按一下每個下拉式清單中的專案時,頁面會傳回,以取得下一個下拉式清單的資料。 因為其視覺效果是由於備份後需要花很長的時間,所以很令人感到頭疼。



如果應用程式的開發人員只使用 XMLHTTP 來檢索資料,而不是回發給,那麼她所遇到的 [不滿] 層級可能很容易緩解。 這就是本月專欄的內容。 我將向您示範如何使用 XMLHTTP 從 Microsoft ASP.NET Web 服務的資料更新部分網頁,而不需要進行回發。 如此一來,真是很棒! 相信我。

一般概覽

XMLHTTP 是透過從用戶端傳送給 Web 服務器的要求,然後返回 XML 資料島來運作。 根據收到的 XML 結構,您可以使用 XSLT 或 XML DOM 來操作它,並將頁面的部分系結到該資料。 這是極其強大的技術。

NoteMicrosoft 確實提供 Internet Explorer 的 Web 服務行為,讓非同步呼叫 ASP.NET Web 服務快速且輕鬆。 不過,這種行為不受支援,而且不是以非同步方式更新頁面的最佳方式。 您應該改用 XMLHTTP!


在本專欄的範例中,我將透過 XMLHTTP 進行三個 Web 服務呼叫至 ASP.NET Web 服務。 Web 服務將在本機 SQL Server 上查詢 Northwind 資料庫,並以 XML diffgram 的形式將資料集傳回給用戶端。 接著,我將使用 XML DOM 來分析該 XML 資料,並動態更新我的頁面部分。 所有這些都將在沒有回發的情況下完成。

Web 服務

我要使用的 Web 服務稱為 [DynaProducts]。 這個基本的 ASP.NET Web 服務是以 c # 撰寫,且包含下列三種方法。

  • GetCategories –傳回包含 [類別] 資料表中所有類別的資料集。

  • GetProducts –傳回包含已傳送給方法之類別之所有產品的資料集。

  • GetProductDetails –傳回包含產品的資料集,該產品的 ProductID 已傳遞給方法。

HTML 頁面

這個範例的第一件事就是,我正在透過 ASP.NET Web 服務進行更新的頁面不是 ASP.NET 網頁。 它只是一般的 HTML 頁面。 不過,我已在頁面上新增了相當數量的用戶端 JavaScript,而這就是進行 Web 服務呼叫的腳本。



我們來看看 HTML 頁面中的第一個程式碼片段。

var objHttp;
var objXmlDoc;

function getDataFromWS(methodName, dataSetName, wsParamValue, wsParamName)
{

// create the XML object
objXmlDoc = new ActiveXObject("Msxml2.DOMDocument");

if (objXmlDoc == null)
{
alert("Unable to create DOM document!");

} else {

// create an XmlHttp instance
objHttp = new ActiveXObject("Microsoft.XMLHTTP");


// Create the SOAP Envelope
strEnvelope = "<soap:Envelope xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +

" xsd=\"http://www.w3.org/2001/XMLSchema\"" +

" soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +

" <soap:Body>" +

" <" + methodName + " xmlns=\"http://jimcoaddins.com/DynaProducts\">" +

" </" + methodName + ">" +

" </soap:Body>" +

"</soap:Envelope>";


// Set up the post
objHttp.onreadystatechange = function(){

// a readyState of 4 means we're ready to use the data returned by XMLHTTP
if (objHttp.readyState == 4)
{

// get the return envelope
var szResponse = objHttp.responseText;

// load the return into an XML data island
objXmlDoc.loadXML(szResponse);

if (objXmlDoc.parseError.errorCode != 0) {
var xmlErr = objXmlDoc.parseError;
alert("You have error " + xmlErr.reason);
} else {

switch(dataSetName)
{
case "CategoriesDS":
processCategory();
break;

case "ProductsDS":
processProducts();
break;

case "ProductDetailDS":
processProductDetails();
break;

}
}

}
}

var szUrl;
szUrl = "http://dadatop/wsXmlHttp/DynaProducts.asmx/" + methodName;

if (wsParamValue != null)
{

szUrl += "?" + wsParamName + "=" + wsParamValue;
}

// send the POST to the Web service
objHttp.open("POST", szUrl, true);
objHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
objHttp.send(strEnvelope);
}
}

這是頁面上最大的程式碼片段,我想要深入瞭解它,讓您瞭解會發生什麼事。



在此腳本區塊的頂端,我建立了兩個變數: objHttp 和 objXmlDoc。 這些是我將用於我的 XMLHTTP 物件和我的 XML DOM 物件的變數。 緊接著,就是 getDataFromWS 函數的函式定義。 這是負責進行用戶端呼叫 Web 服務的函數。 它會採用下列四個引數,其中兩個是選擇性的:

  • 方法名稱-要在 Web 服務上呼叫的方法名稱。

  • dataSetName –由 Web 服務傳回的資料集的名稱。

  • wsParamValue –傳遞至 Web 服務的參數值(如果適用的話)。 (選用)

  • wsParamName –傳遞至 Web 服務的參數名稱(如果適用的話)。 (選用)

讓我們將 getDataFromWS 函數分解成多個部分,並討論每個部分。 以下是第一個程式碼片段:

// create the XML object
objXmlDoc = new ActiveXObject("Msxml2.DOMDocument");

if (objXmlDoc == null)
{
alert("Unable to create DOM document!");

} else {

// create an XMLHTTP instance
objHttp = new ActiveXObject("Microsoft.XMLHTTP");

這段程式碼會建立 XMLHTTP 物件和 XML Document 物件。 接下來,我開始建立 SOAP 信封。

// Create the SOAP Envelope
strEnvelope = "<soap:Envelope xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +

" xsd=\"http://www.w3.org/2001/XMLSchema\"" +

" soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +

" <soap:Body>" +

" <" + methodName + " xmlns=\"http://jimcoaddins.com/DynaProducts\">" +

" </" + methodName + ">" +

" </soap:Body>" +

"</soap:Envelope>";

在這個程式碼中,我將 SOAP 信封指派給字串變數,以便將它傳遞到 Web 服務。 您可以很容易地瞭解如何為您的 Web 服務設定 SOAP 信封格式。 只要流覽至 Web 服務,然後按一下其中一個方法,就能查看該方法的 SOAP 信封。 例如,當您流覽至我在本文中建立的 wsXMLHTTP Web 服務的 GetCategories 方法時,會看到以下訊息:

替代文字

ASP.NET 會告訴您如何針對 HTTP 文章和 HTTP 取得格式化 SOAP 信封。 在本文所述的範例中,我將使用 HTTP 文章。



目前為止,一切都好。 現在,我們來看看下一個程式碼區段。

// Set up the post
objHttp.onreadystatechange = function(){

// a readyState of 4means we're ready to use thedata returned byXMLHTTP
if (objHttp.readyState == 4)
{

// getthe return envelope
varszResponse= objHttp.responseText;

// loadthe return into an XML data island
objXmlDoc.loadXML(szResponse);

if (objXmlDoc.parseError.errorCode != 0) {
var xmlErr =objXmlDoc.parseError;
alert("You have error " + xmlErr.reason);
}
else
{

switch(dataSetName)
{
case "CategoriesDS":
processCategory();
break;
case "ProductsDS":
processProducts();
break;
case "ProductDetailDS":
processProductDetails();
break;

}
}

透過 XMLHTTP 發出要求時,XMLHTTP 物件會使用 readyState 屬性來追蹤要求的狀態。 從 Web 服務收到所有資料後,readyState 屬性會變更為4的值。 XMLHTTP 程式物件的 onreadystatechange 屬性可讓您設定在 readyState 屬性變更時要呼叫的回呼函數。 透過確保完整地收到資料,我就可以繼續操作該資料,直到我準備就緒為止。



收到所有資料之後,我就可以使用 responseText 屬性,透過回應來建立 XML 資料島。 您可能知道,來自 Web 服務的回應是 XML 格式。 在這種情況下,我會傳回 Microsoft ADO.NET 資料集。



這個程式碼區塊的下一節會使用 switch 語句,根據從 Web 服務傳回的資料集名稱來呼叫適當的函數。 接著,我將在稍後的程式碼中詳細討論這些函數。


現在,我們來看看實際執行 XMLHTTP 要求的程式碼。

var szUrl;
szUrl = "http://dadatop/wsXmlHttp/DynaProducts.asmx/" + methodName;

if (wsParamValue != null)
{

szUrl += "?" + wsParamName + "=" + wsParamValue;
}

// send the POST to the Web service
objHttp.open("POST", szUrl, true);
objHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
objHttp.send(strEnvelope);

由於清楚起見,變數 szUrl 包含用來呼叫 Web 服務的 URL。 接著,我有一個 if 語句,該語句會 tacks 任何傳成 QueryString 值的參數。 在您的環境中,您可能會想要將參數新增至 SOAP 信封。 這兩種方法都能正常運作。



[XMLHTTP] 物件的 open 方法稱為 [下一步]。 我已使用 open 方法的前三個引數;方法、URL,以及指定呼叫是否為非同步布林值。
重要如果您要在這裡進行非同步呼叫,您必須透過 onreadystatechanged 屬性設定回呼函數。

設定內容類型的要求標頭之後,我會使用先前已填入的字串變數,以 SOAP 信封傳送該要求。



現在,我們已在進行 XMLHTTP 要求的所有程式碼上,都已過期。 現在,我們來看看在瀏覽器中處理介面的程式碼,並處理來自 Web 服務呼叫的回應。

首先,我們來看看第一次載入頁面時所呼叫的函數。

function getCategories()
{

var func = "getDataFromWS('GetCategories', 'CategoriesDS')";
document.all.lblCategoryDropdown.innerText =
"Please wait while data is retrieved...";
window.setTimeout(func, 1);

}

我在這個函數中的第一件事,就是建立一個變數來儲存 getDataFromWS 的函數簽名。 之所以這麼做,是因為我將在這個函數的結尾撥打電話 setTimeout,以呼叫 getDataFromWS 函數。 這個方法的用途是允許我在等待 Web 服務呼叫完成時,將狀態顯示給使用者。 請注意,我要變更 DIV 的 innerText,以顯示訊息,指出正在檢索資料。 接著,我會透過視窗排程 getDataFromWS 函數,並將它設定為在1毫秒內執行。

處理 Web 服務回應

請記住,我已使用 onreadystatechanged 屬性來設定回呼函數。 另請記住,callback 函數包含的 switch 語句會根據資料集名稱來呼叫特定的函數。 在此情況下,我們的資料集名稱是 CategoriesDS。 因此,會從 callback 函數呼叫 processCategory 函數。 讓我們來看看這個函數,瞭解如何使用 XML DOM 來分析來自 Web 服務的回應。

function processCategory()
{

// get an XML data island with the category data
objNodeList = objXmlDoc.getElementsByTagName("Categories");

// add default value to the drop-down
document.forms[0].drpCategory.options[0] = new Option("Select a Category", 0);

// walk through the nodeList and populate the drop-down
for (var i = 0; i < objNodeList.length; i++)
{
var dataNodeList;
var textNode;
var valueNode;

dataNodeList = objNodeList[i].childNodes;
valueNode = dataNodeList.item(0);
textNode = dataNodeList.item(1);

document.forms[0].drpCategory.options[i + 1] =
new Option(textNode.text, valueNode.text);
document.all.lblCategoryDropdown.innerText = "Select a Category:";
document.forms[0].drpCategory.style.visibility = "visible";

}

}

請記住,getDataFromWS 函數已從回應載入 XML 到 objXmlDoc 物件。 在 processCategory 函數中,我會使用該 XML,並分析它以填入 [類別] 下拉式清單。



我所做的第一件事是使用 XML 回應的一部分來建立 IXMLDOMNodeList 物件。 從 Web 服務通話中傳回的資料集是以 diffgram 的形式傳回,而且我真正感興趣之回應的唯一部分是我已插入資料集中的 DataTable 資料。 我可以從包含 DataTable 的 XML 區塊建立 IXMLDOMNodeList 物件來取得這個目標。



如果您查看 Web 服務的程式碼,您會看到我建立一個名為「類別」的 DataTable,並將它新增到資料集。 從 Web 服務傳回 XML 時,DataSet 會包含在 <CategoriesDS> 區塊中,而每個 DataTable 資料列都包含在不同的 <類別中> 區塊,如下列 XML 檔案所示。

下列檔案可從 Microsoft 下載中心下載:
下載 立即下載 GetCategories.xml 套件。
下載 立即下載 WSXMLHTTP.exe 套件。如需有關如何下載 Microsoft 支援檔案的詳細資訊,請按一下下列文章編號,以查看 Microsoft 知識庫中的文章:

119591 如何從線上服務取得 Microsoft 支援檔案
Microsoft 已針對病毒掃描此檔案。 Microsoft 是利用發佈當日的最新病毒偵測軟體來掃描檔案。 檔案會儲存在安全性強化的伺服器上,以避免任何未經授權的變更。


若要取得包含該 DataTable 的 XML 區塊,請使用下列程式碼:

objNodeList = objXmlDoc.getElementsByTagName("Categories");

這會傳回 IXMLDOMNodeList 物件,其中包含每個 <類別> 節點。 接著,我會使用 for 迴圈來迴圈流覽該清單。

// walk through the nodeList and populate the drop-down
for (var i = 0; i < objNodeList.length; i++)
{
var dataNodeList;
var textNode;
var valueNode;

dataNodeList = objNodeList[i].childNodes;
valueNode = dataNodeList.item(0);
textNode = dataNodeList.item(1);

document.forms[0].drpCategory.options[i + 1] =
new Option(textNode.text, valueNode.text);
document.all.lblCategoryDropdown.innerText = "Select a Category:";
document.forms[0].drpCategory.style.visibility = "visible";

}

我已經知道每個 <類別> 節點都會有兩個需要的節點: <ID> 節點,以及 <類別 \ [>] 節點。 因此,我所做的第一件事就是建立新的 IXMLDOMNodeList,並使用目前 <類別> 節點的子節點來填入它。

dataNodeList = objNodeList[i].childNodes;

接著,我使用 item 方法來存取我所需的兩個節點來填入下拉式清單。 第一個節點包含資料庫中的 [類別 Id] 欄位,第二個節點包含資料庫中的 [類別 1] 欄位。 我建立新的選項物件,將文字設定為 [類別名稱],將值設定為 [類別 Id],然後將其新增至 [drpCategory] 下拉式清單。 在其餘函數中使用的程式碼會使用相同的方法,從 XML 回應提取所需的資料,並填入頁面的部分內容。

NoteSince 我們正在處理少量的資料,使用 DOM 是拉出所需資料的絕佳方式。 如果您正在處理大量的資料,您可以選擇改用 XSLT。

如何讓它發揮作用

現在,我已涵蓋所有這一切運作方式的相關詳細資訊,您可以在此瞭解如何使用內含的範例檔案,讓您自己能正常運作。

部署 Web 服務

若要部署 ASP.NET Web 服務,只要將附加的 Web 服務範例解壓縮至您的 Web 服務器根目錄即可。 接著您需要開啟 DynaProducts 的程式碼,並變更連接字串。 至少,您必須輸入 SA 密碼。 進行變更之後,請重新編譯 Web 服務。

部署 HTML 檔案

HTML 檔案包含一個名為 szUrl 的變數,其中包含該 Web 服務的 URL。 您會在函數底部附近的 getDataFromWS 函數中找到這個變數。 您必須將其變更為您在上述部署之 Web 服務的 URL。


在您部署 Web 服務和 HTML 檔案之後,請流覽至 HTML 檔案。 載入時,會將第一個 XMLHTTP 要求填入至 Web 服務的類別下拉式清單。 一旦已填入,請選取一個類別,以啟動下一個填入 [產品] 下拉式清單的 XMLHTTP 要求。 從 [產品] 下拉式清單中選取 [產品],就會填入含該產品相關資料的資料表。



請注意,此頁面在任何 XMLHTTP 要求中都無法回發。 這就是 XMLHTTP 要求的優點。 如果我在大型頁面上進行過此動作,此頁面也會維持其滾動位置,而不會在使用者「閃爍」。 如果您問我,那是一件相當強大的東西!



另一件事:本文將使用 XMLHTTP 查詢 Web 服務。 我可以輕鬆地使用它來針對 ASPX 頁面或 ASP 頁面提出要求。 您可以採用這種技術的可能性。 我希望您在未來的 Web 應用程式開發中發現 XMLHTTP 實用程式。

就像往常一樣,您可以在未來的專欄中或在 Microsoft 知識庫中使用 [ 要求 It ] 表單,隨意提交想法。

需要更多協助嗎?

想要其他選項嗎?

探索訂閱權益、瀏覽訓練課程、瞭解如何保護您的裝置等等。

社群可協助您詢問並回答問題、提供意見反應,以及聆聽來自具有豐富知識的專家意見。

這項資訊有幫助嗎?

您對語言品質的滿意度如何?
以下何者是您會在意的事項?
按下 [提交] 後,您的意見反應將用來改善 Microsoft 產品與服務。 您的 IT 管理員將能夠收集這些資料。 隱私權聲明。

感謝您的意見反應!

×