Dynamische pagina-updates met XMLHTTP

ASP.NET De kolom Spraak ondersteunen

Dynamische pagina-updates met XMLHTTP

Als u deze kolom aan uw wensen wilt aanpassen, nodigen we u uit om uw ideeën over onderwerpen in te dienen die voor u interessant zijn en onderwerpen die u wilt bespreken in toekomstige Knowledge Base-artikelen en ondersteuningskolommen voor spraak. U kunt uw ideeën en feedback verzenden via het formulier Vragen om het verzoek. Er is ook een koppeling naar het formulier onder aan deze kolom.

Inleiding

Een van mijn favoriete manieren om de bruikbaarheid van webtoepassing te bestuderen, is om mijn vrouw te zien navigeren op een website. Ze kan goed weg vinden op internet, maar ze weet weinig over de technische aspecten op laag niveau (wat ze 'de 'spullen') noemt, die het allemaal doen.



Op een recente avond kijk ik hoe mijn vrouw een e-commerce-toepassing gebruikt van een van de grote jongens. Ze wilde een productvermelding bekijken door meerdere vervolgkeuzelijsten te gebruiken, elke vermelding uit de eerder gemaakte selectie. Wanneer ze in elke vervolgkeuzepagina op een item klikte, werd de pagina terug geplaatst om gegevens op te halen voor de volgende vervolgkeuzepagina. De ervaring was frustrerend voor haar omdat haar indruk was dat het lang duurt vanwege de back-backs van het bericht.



De frustratie die ze ondervindt, kan gemakkelijk worden verminderd door de ontwikkelaars van de toepassing als ze alleen XMLHTTP gebruiken om de gegevens op te halen in plaats van terug te plaatsen. Daar gaat de kolom van deze maand over. Ik zal u laten zien hoe u XMLHTTP gebruikt om een gedeelte van een webpagina bij te werken met gegevens van een Microsoft ASP.NET-webservice zonder een post terug te plaatsen. Dit wordt heel leuk! Vertrouw me nou maar.

Algemeen overzicht

XMLHTTP werkt door een aanvraag vanuit de client naar de webserver te verzenden en een XML-gegevenseiland te retourneren. Afhankelijk van de structuur van de XML die wordt ontvangen, kunt u XSLT of de XML DOM gebruiken om de XML-dom te manipuleren en delen van de pagina aan die gegevens te binden. Dit is een zeer krachtige techniek.

NoteMicrosoft biedt wel een webservicegedrag voor Internet Explorer, waardoor asynchroon bellen naar ASP.NET webservices snel en eenvoudig is. Dit gedrag wordt echter niet ondersteund en dit is niet de beste manier om een pagina asynchroon bij te werken. U moet XMLHTTP gebruiken!


In het voorbeeld dat ik in deze kolom doorwerk, ga ik drie webservicegesprekken voeren naar een ASP.NET webservice via XMLHTTP. De webservice queryteert de Northwind-database op de lokale SQL Server en retourneert een gegevensset voor de client in de vorm van een XML-diffgram. Vervolgens gebruik ik de XML DOM om die XML-gegevens te parseren en delen van mijn pagina dynamisch bij te werken. Dit alles gebeurt zonder een bericht terug te plaatsen.

De webservice

De webservice die ik gebruik, heet DynaProducts. Het is een eenvoudige ASP.NET webservice die in C# is geschreven en die de volgende drie methoden bevat.

  • GetCategories: retourneert een gegevensset die alle categorieën in de tabel Categorieën bevat.

  • GetProducts: retourneert een gegevensset die alle producten van de categorie bevat die aan de methode worden doorgegeven.

  • GetProductDetails: retourneert een gegevensset met details over het product waarvan de product-id aan de methode wordt doorgegeven.

De HTML-pagina

Het eerste wat u mogelijk opstak in dit voorbeeld is dat de pagina die ik bij werk, hoewel de ASP.NET-webservice geen ASP.NET is. Het is gewoon een gewone HTML-pagina. Ik heb echter een redelijk aantal JavaScript aan de clientzijde toegevoegd aan de pagina en dat script zorgt ervoor dat de oproepen naar de webservice worden gedaan.



Laten we eens kijken naar het eerste codefragment van de HTML-pagina.

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);
}
}

Dit is het grootste stukje code van de pagina en ik wil dit gedetailleerd bekijken, zodat u begrijpt wat er aan de hand is.



Boven aan dit scriptblok heb ik twee variabelen gemaakt: objHttp en objXmlDoc. Dit zijn de variabelen die ik voor mijn XMLHTTP-object en mijn XML DOM-object gebruik. Direct daarna wordt de functiedefinitie voor de functie getDataFromWS gebruikt. Dit is de functie die verantwoordelijk is voor het bellen via de client naar de webservice. Deze heeft de volgende vier argumenten, waarvan twee optioneel zijn:

  • methodName: de naam van de methode die u wilt bellen op de webservice.

  • dataSetName: de naam van de gegevensset die door de webservice wordt geretourneerd.

  • wsParamValue: de waarde van de parameter die, indien van toepassing, wordt doorgegeven aan de webservice. (Optioneel)

  • wsParamName: de naam van de parameter die, indien van toepassing, wordt doorgegeven aan de webservice. (Optioneel)

We delen de functie getDataFromWS in delen en bespreken elke functie. Dit is het eerste fragment:

// 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");

Dit codeblok maakt het XMLHTTP-object en het XML-documentobject. Vervolgens maak ik de SOAP-envelop.

// 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>";

In deze code wijs ik de SOAP-envelop toe aan een tekenreeksvariabele, zodat ik deze kan doorgeven aan de webservice. Het is eigenlijk vrij eenvoudig om te ontdekken hoe u de SOAP-envelop opmaken voor uw webservice. Blader naar de webservice en klik op een van de methoden om een SOAP-envelop voor die methode weer te geven. Dit is bijvoorbeeld wat ik zie wanneer ik blader naar de methode GetCategories van de wsXMLHTTP-webservice die ik voor dit artikel heb gemaakt:alternatieve tekstASP.NET laat u weten hoe de SOAP-envelop moet worden opgemaakt voor een



HTTP-POST en http-get. In het voorbeeld dat in dit artikel wordt beschreven, gebruik ik HTTP POST.



Tot dusverre goed. Laten we nu eens kijken naar de volgende sectie met code.

// 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;

}
}

Wanneer een aanvraag wordt ingediend via XMLHTTP, gebruikt het XMLHTTP-object een readyState-eigenschap om de status van de aanvraag bij te houden. Wanneer alle gegevens zijn ontvangen van de webservice, verandert de eigenschap ReadyState in de waarde 4. Met de onreadystatechange-eigenschap voor het XMLHTTP-object kunt u een callback-functie instellen die wordt aangeroepen wanneer de eigenschap ReadyState wordt gewijzigd. Door ervoor te zorgen dat de gegevens in zijn geheel zijn ontvangen, kan ik die gegevens blijven gebruiken totdat ik klaar ben.



Nadat alle gegevens zijn ontvangen, maak ik een XML-gegevenseiland met het antwoord met behulp van de eigenschap ResponseText. Zoals u waarschijnlijk weet, heeft het antwoord van een webservice de XML-indeling. In dit geval retourn terugkeer ik een Microsoft ADO.NET DataSet.



In het volgende gedeelte van dit codeblok wordt een schakelverklaring gebruikt om de betreffende functie aan te roepen op basis van de naam van de gegevensset die wordt geretourneerd van de webservice. Ik ga even verder met de code voor deze functies.


Laten we nu eens kijken naar de code die de XMLHTTP-aanvraag uitvoert.

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);

De variabele szUrl bevat de URL die wordt gebruikt om de webservice aan te roepen om duidelijkheid te scheppen. Vervolgens heb ik een IF-instructie die een waarde als een querystring toekent aan parameters die worden doorgegeven. In uw omgeving kunt u de parameters toevoegen aan de SOAP-envelop. Voor beide werkt het prima.



De open methode van het XMLHTTP-object wordt als volgende aangeroepen. Ik heb de eerste drie argumenten voor de open methode gebruikt. de methode, de URL en een Booleaanse waarde die aangeeft of de oproep asynchroon is.
Belangrijk Als u een asynchroon gesprek tot leven komt zoals ik hier ben, moet u een callback-functie instellen via de eigenschap onreadystatechanged.

Nadat de aanvraagkoptekst voor het inhoudstype is ingesteld, verzend ik de aanvraag als een SOAP-envelop met behulp van de tekenreeksvariabele die ik eerder heb ingevuld.



We hebben nu alle code overgenomen die de XMLHTTP-aanvraag maakt. Laten we nu eens kijken naar de code die de interface in de browser verwerkt en die de reactie van de webserviceoproep verwerkt.

We kijken eerst naar de functie die wordt genoemd wanneer de pagina voor het eerst wordt geladen.

function getCategories()
{

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

}

Het eerste wat ik in deze functie doe, is een variabele maken om de functiehandtekening voor getDataFromWS op te slaan. Ik doe dit omdat ik window.setTimeout aan het einde van deze functie ga aanroepen om de functie getDataFromWS aan te roepen. Het doel van deze methode is dat ik de status kan weergeven aan de gebruiker terwijl ik wacht tot de oproep van de webservice is voltooid. Zoals u ziet, verandert ik de innerTekst van een DEEL zodat een bericht wordt weergegeven dat gegevens worden opgehaald. Vervolgens plan ik de functie getDataFromWS via het window.setTimeout-gesprek en stel ik in dat deze in één milliseconde wordt uitgevoerd.

Het antwoord op de webservice wordt verwerkt

Ik heb eerder de eigenschap onreadystatechanged gebruikt om een callback-functie te configureren. Vergeet ook niet dat de functie terugbellen een schakelinsteling bevat die een bepaalde functie aanroept op basis van de gegevenssetnaam. In dit geval is de naam Van gegevensset Categorieën. Daarom wordt de functie processCategory aangeroepen vanuit de functie callback. Laten we eens kijken naar deze functie om te zien hoe de XML DOM wordt gebruikt om het antwoord van de webservice te parseren.

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";

}

}

Houd er rekening mee dat de functie getDataFromWS XML vanuit het antwoord in het objXmlDoc-object heeft geladen. In de functie processcategory neem ik die XML en parser ik er doorheen om de vervolgkeuzekeuzecategorie te vullen.



Het eerste wat ik doe, is een IXMLDOMNodeList-object maken met een deel van de XML-reactie. De gegevensset die ik terug ga van de webserviceoproep, wordt geretourneerd als een diffgram en het enige deel van dat antwoord waarin ik echt geïnteresseerd ben, is de gegevens uit de gegevenstabel die ik in de gegevensset heb ingevoegd. Dat kan door een IXMLDOMNodeList-object te maken vanuit het XML-blok dat de gegevenstabel bevat.



Als u de code voor de webservice bekijkt, ziet u dat ik een gegevenstabel met de naam Categorieën maak en deze aan de gegevensset toevoeg. Wanneer de XML wordt geretourneerd vanuit de webservice, is de Gegevensset opgenomen in een <CategoriesDS>-blok en is elke rij van de gegevenstabel opgenomen in afzonderlijke <Categories>-blokken, zoals wordt weergegeven in het onderstaande XML-bestand.

De volgende bestanden kunt u downloaden in het Microsoft Downloadcentrum:
Downloaden Het GetCategories.xml nu downloaden.
Downloaden nu het WSXMLHTTP.exe downloaden.Klik op het volgende artikelnummer om het artikel in de Microsoft Knowledge Base te bekijken voor meer informatie over het downloaden van Microsoft-ondersteuningsbestanden:

119591 Het verkrijgen van Microsoft-ondersteuningsbestanden van onlineservices die Microsoft heeft gescand
op virussen. Hierbij is gebruikgemaakt van software voor virusdetectie die volledig bijgewerkt was op de datum dat het bestand beschikbaar werd gesteld. Het bestand is opgeslagen op beveiligde servers die onbevoegde wijzigingen aan het bestand helpen voorkomen.


Ik gebruik de volgende code om het XML-blok op te halen dat deze gegevenstabel bevat:

objNodeList = objXmlDoc.getElementsByTagName("Categories");

Het retourneert een IXMLDOMNodeList-object dat elk <voor> knooppunt bevat. Vervolgens doorloop ik die lijst met een lus.

// 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";

}

Ik weet al dat elk knooppunt <Categorieën> twee knooppunten heeft die ik nodig heb: het knooppunt <-id> en het knooppunt <Categorienaam>. Daarom maak ik als eerste een nieuwe IXMLDOMNodeList en vult u deze met de onderliggende knooppunten van het huidige knooppunt <categorieën> knooppunt.

dataNodeList = objNodeList[i].childNodes;

Vervolgens gebruik ik de itemmethode om de beide knooppunten te openen die ik in mijn vervolgkeuzekeuze moet vullen. Het eerste knooppunt bevat het veld Categorie-id uit de database en het tweede knooppunt bevat het veld Categorienaam uit de database. Ik maak een nieuw Option-object, stel de tekst in op Categorienaam, stel de waarde in op Categorie-id en voeg deze toe aan de vervolgkeuzepcategory. Voor de code die in de resterende functies wordt gebruikt, wordt dezelfde methode gebruikt om de benodigde gegevens op te halen uit het XML-antwoord en delen van de pagina te vullen.

NoteSince we're dealing with small amounts of data here, using the DOM is a great way to pull out the data we need. Als u te maken had met een grote hoeveelheid gegevens, kunt u ervoor kiezen om in plaats daarvan XSLT te gebruiken.

Hoe u alles kunt laten werken

Nu ik alle details heb behandeld over hoe dit allemaal werkt, is het tijd om te bekijken hoe u de voorbeeldbestanden kunt gebruiken om te zien hoe het werkt.

De webservice implementeren

Als u de ASP.NET webservice wilt implementeren, hoeft u alleen het bijgevoegde webservicevoorbeeld uit te zetten naar de hoofdmap van uw webserver. Vervolgens moet u de code voor DynaProducts.asmx openen en de verbindingsreeks wijzigen. U moet in ieder geval het sa-wachtwoord invoeren. Nadat u deze wijziging hebt aangebracht, kunt u de webservice opnieuw aanvullen.

Het HTML-bestand implementeren

Het HTML-bestand bevat een variabele met de naam szUrl die een URL naar de webservice bevat. U vindt deze variabele in de functie getDataFromWS onderaan de functie. U moet deze wijzigen in de URL voor de webservice die u hierboven hebt geïmplementeerd.


Nadat u zowel de webservice als het HTML-bestand hebt geïmplementeerd, bladert u naar het HTML-bestand. Wanneer de categorie wordt geladen, wordt de eerste XMLHTTP-aanvraag voor de webservice ingevuld. Zodra deze is ingevuld, selecteert u een categorie om de volgende XMLHTTP-aanvraag af te sluiten waarin de vervolgkeuzekeuze met producten wordt ingevuld. Als u een product selecteert in de vervolgkeuzelijst Producten, wordt er een tabel met gegevens over dat product ingevuld.



U ziet dat de pagina niet wordt terug geplaatst tijdens een van deze XMLHTTP-aanvragen. Dat is het mooie van XMLHTTP-aanvragen. Als ik dit op een grote pagina had gedaan, had de pagina ook de schuifpositie behouden zonder "knipperend" bij de gebruiker. Als u het mij vraagt, zijn dat nogal krachtige dingen!



Nog één ding: in dit artikel heb ik XMLHTTP gebruikt om een query uit te voeren op een webservice. Ik had het net zo gemakkelijk kunnen gebruiken om een aanvraag te doen voor een ASPX-pagina of een ASP-pagina. De mogelijkheden voor het gebruik van deze technologie zijn eindeloos. Ik hopen dat u XMLHTTP nuttig vindt bij de ontwikkeling van webtoepassing in de toekomst.

Zoals altijd kunt u ideeën indienen over onderwerpen die u wilt bespreken in toekomstige kolommen of in de Microsoft Knowledge Base met behulp van het formulier Vragen om it.

Meer hulp nodig?

Uw vaardigheden uitbreiden
Training verkennen
Als eerste nieuwe functies krijgen
Deelnemen aan Microsoft insiders

Was deze informatie nuttig?

Bedankt voor uw feedback.

Hartelijk dank voor uw feedback! Het lijkt ons een goed idee om u in contact te brengen met een van onze Office-ondersteuningsagenten.

×