Mises à jour de pages dynamiques à l'aide de XMLHTTP

Traductions disponibles Traductions disponibles
Numéro d'article: 893659 - Voir les produits auxquels s'applique cet article
Chronique ASP.NET Support Voice

Mises à jour de pages dynamiques à l'aide de XMLHTTP

Pour personnaliser cette chronique selon vos besoins, nous vous invitons à nous faire part des rubriques qui vous intéressent et des problèmes que vous souhaiteriez voir traités dans de futurs articles de la Base de connaissances et des chroniques Support Voice. Vous pouvez nous envoyer vos commentaires par le biais du formulaire Ask For It (en anglais). Vous trouverez également un lien vers le formulaire au bas de cette chronique.
Agrandir tout | Réduire tout

Sommaire

INTRODUCTION

L'une de mes manières préférées d'étudier la facilité d'utilisation d'une application Web consiste à regarder ma femme naviguer sur un site Web. Elle sait comment faire pour naviguer sur Internet, mais elle en sait peu sur les aspects techniques de bas niveau (ce qu'elle appelle « les trucs ennuyeux ») qui font en sorte que tout cela fonctionne.

Il y a quelque temps, un soir, je la regardais en train de consulter une application de commerce électronique d'un grand distributeur. Elle effectuait une recherche dans une liste de produits à l'aide de plusieurs listes déroulantes, chacune dépendant de la sélection effectuée précédemment. À mesure qu'elle cliquait sur un élément dans chaque liste déroulante, la page était republiée afin d'obtenir des données pour la liste déroulante suivante. Cette expérience était frustrante car tout ce processus prenait beaucoup de temps.

Son niveau de frustration aurait pu être allégé facilement par les développeurs de l'application si seulement ils avaient utilisé XMLHTTP pour récupérer les données au lieu de republier la page. C'est de cela dont nous allons discuter ce mois-ci. Je vais vous montrer comment utiliser XMLHTTP pour mettre à jour une partie d'une page Web avec des données d'un service Web Microsoft ASP.NET sans effectuer de publication. Nous allons bien nous amuser ! Faites-moi confiance...

Vue d'ensemble

Le fonctionnement est le suivant : XMLHTTP envoie une demande au serveur Web à partir du client et retourne un îlot de données XML. Selon la structure des données XML reçues, vous pouvez utiliser XSLT ou le DOM XML pour les manipuler et lier des parties de la page à ces données. Il s'agit d'une technique extrêmement puissante.

Remarque Microsoft offre un comportement de service Web pour Internet Explorer qui effectue des appels asynchrones à des services Web ASP.NET rapidement et facilement. Toutefois, ce comportement n'est pas pris en charge et ce n'est pas le meilleur moyen de mettre à jour une page de façon asynchrone. Je vous conseille plutôt d'utiliser XMLHTTP !

Dans l'exemple de cette chronique, j'effectuerai trois appels de service Web à un service Web ASP.NET par le biais de XMLHTTP. Le service Web interrogera la base de données Les Comptoirs sur le serveur SQL Server local et retournera un DataSet au client sous la forme d'un diffgram XML. J'utiliserai ensuite le DOM XML pour analyser ces données XML et mettre à jour des parties de ma page de manière dynamique. Tout cela sera fait sans publication.

Le service Web

Le service Web que j'utiliserai se nomme DynaProducts. Il s'agit d'un service Web ASP.NET de base écrit en C# et qui contient les trois méthodes suivantes.
  • GetCategories - Retourne un DataSet qui contient toutes les catégories de la table Categories.
  • GetProducts - Retourne un DataSet qui contient tous les produits de la catégorie qui sont passés à la méthode.
  • GetProductDetails - Retourne un DataSet qui contient des détails sur le produit dont le ProductID est passé à la méthode.

La page HTML

La première chose qui peut vous frapper à propos de cet exemple est que la page que je mets à jour par le biais du service Web ASP.NET n'est pas une page ASP.NET. Il s'agit d'une page HTML ordinaire. Toutefois, j'y ai ajouté une certaine quantité de JavaScript côté client, et c'est ce script qui effectue les appels au service Web.

Examinons le premier extrait de code de la page 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);
	  }
}
S'agissant du plus grand bloc de code de la page, nous allons l'examiner en détail afin que vous compreniez bien ce qui se passe.

En haut de ce bloc de script, j'ai créé deux variables : objHttp et objXmlDoc. Il s'agit des variables que j'utiliserai pour mon objet XMLHTTP et mon objet DOM XML. Juste après se trouve la définition de fonction pour la fonction getDataFromWS. Il s'agit de la fonction chargée d'effectuer l'appel côté client au service Web. Elle prend les quatre arguments suivants, dont deux sont facultatifs :
  • methodName ? Le nom de la méthode à appeler sur le service Web.
  • dataSetName ? Le nom du DataSet retourné par le service Web.
  • wsParamValue ? La valeur du paramètre qui est passé au service Web, le cas échéant. (Facultatif)
  • wsParamName ? Le nom du paramètre qui est passé au service Web, le cas échéant. (Facultatif)
Nous allons maintenant fractionner la fonction getDataFromWS en plusieurs parties et discuter chacune d'elles. Voici le premier extrait de code :
// 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");
Ce bloc de code crée l'objet XMLHTTP et l'objet XML Document. Ensuite, je commence à créer l'enveloppe 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>";
Dans ce code, j'assigne l'enveloppe SOAP à une variable chaîne afin de pouvoir la passer au service Web. En fait, il est très facile de découvrir comment mettre en forme l'enveloppe SOAP pour votre service Web. Naviguez simplement jusqu'au service Web et cliquez sur l'une des méthodes pour afficher une enveloppe SOAP pour cette méthode. Par exemple, voici ce qui s'affiche lorsque je navigue jusqu'à la méthode GetCategories du service Web wsXMLHTTP que j'ai créé pour cet article :

Réduire cette imageAgrandir cette image
envelope.png


ASP.NET vous indique comment l'enveloppe SOAP doit être mise en forme pour une demande HTTP POST et une demande HTTP GET. Dans l'exemple présenté dans cet article, j'utiliserai HTTP POST.

Jusqu'ici, tout va bien. Examinons maintenant la section de code suivante.
// 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;

				}
			}
Lorsqu'une demande est effectuée par le biais de XMLHTTP, l'objet XMLHTTP utilise une propriété readyState pour assurer le suivi de l'état de la demande. Lorsque toutes les données ont été renvoyées par le service Web, la propriété readyState se transforme en une valeur 4. La propriété onreadystatechange de l'objet XMLHTTP vous permet de configurer une fonction de rappel qui sera appelée en cas de modification de la propriété readyState. En m'assurant que les données ont été reçues dans leur intégralité, je peux me permettre d'attendre d'être prêt pour agir sur ces données.

Une fois que toutes les données ont été reçues, je crée un îlot de données XML avec la réponse en utilisant la propriété responseText. Comme vous le savez probablement, la réponse d'un service Web est au format XML. Dans ce cas, je retourne un DataSet Microsoft ADO.NET.

La section suivante de ce bloc de code utilise une instruction switch pour appeler la fonction appropriée en fonction du nom du DataSet retourné par le service Web. J'examinerai en détail le code de ces fonctions un peu plus loin.

Examinons maintenant le code qui effectue la demande 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);
Pour des raisons de clarté, la variable szUrl contient l'URL utilisée pour appeler le service Web. J'ai ensuite une instruction if qui s'attache à tout paramètre passé comme valeur QueryString. Dans votre environnement, vous souhaiterez peut-être ajouter les paramètres à l'enveloppe SOAP. D'une manière ou d'une autre, cela fonctionnera correctement.

La méthode open de l'objet XMLHTTP est ensuite appelée. J'ai utilisé les trois premiers arguments pour la méthode open ; la méthode, l'URL et une valeur booléenne qui spécifie si l'appel est asynchrone.
Important Si vous effectuez un appel asynchrone, comme je le fais ici, vous devez configurer une fonction de rappel par le biais de la propriété onreadystatechanged.

Une fois que l'en-tête de demande pour le content-type est défini, j'envoie la demande en tant qu'enveloppe SOAP à l'aide de la variable chaîne que j'ai remplie précédemment.

Nous venons d'examiner tout le code qui effectue la demande XMLHTTP. Jetons maintenant un coup d'?il au code qui gère l'interface dans le navigateur et qui gère la réponse de l'appel de service Web.

Nous allons tout d'abord examiner la fonction qui est appelée lors du premier chargement de la page.
function getCategories()
{

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

  }
La première chose que je fais dans cette fonction est de créer une variable pour stocker la signature de la fonction pour getDataFromWS, car je vais appeler window.setTimeout à la fin de cette fonction pour appeler la fonction getDataFromWS. L'objectif de cette approche est de me permettre d'afficher l'état à l'utilisateur en attendant que l'appel du service Web soit terminé. Notez que je modifie l'innerText d'un DIV pour afficher un message indiquant que des données sont en cours de récupération. Je planifie ensuite la fonction getDataFromWS par le biais de l'appel window.setTimeout et je la configure pour s'exécuter en une milliseconde.

Traitement de la réponse du service Web

Souvenez-vous que, plus haut, j'ai utilisé la propriété onreadystatechanged pour configurer une fonction de rappel. Souvenez-vous également que la fonction de rappel contient une instruction switch qui appelle une fonction particulière basée sur le nom du DataSet. Dans le cas présent, le nom de notre DataSet est CategoriesDS. Par conséquent, la fonction processCategory sera appelée à partir de la fonction de rappel. Jetons un coup d'?il à cette fonction pour voir comment utiliser le DOM XML afin d'analyser la réponse du service 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";
       
    }

  }
Souvenez-vous que la fonction getDataFromWS a chargé des données XML à partir de la réponse dans l'objet objXmlDoc. Dans la fonction processCategory, je prends ces données XML et je les analyse pour remplir la liste déroulante Category.

La première chose que je fais est de créer un objet IXMLDOMNodeList à l'aide d'une partie de la réponse XML. Le DataSet que je retourne à partir de l'appel de service Web est retourné en tant que diffgram et la seule partie de cette réponse qui m'intéresse vraiment, ce sont les données du DataTable que j'ai insérées dans le DataSet. Je peux y accéder en créant un objet IXMLDOMNodeList à partir du bloc XML qui contient le DataTable.

Si vous examinez le code du service Web, vous verrez que je crée un DataTable nommé Categories, que j'ajoute au DataSet. Lorsque les données XML sont retournées à partir du service Web, le DataSet est contenu dans un bloc <CategoriesDS> et chaque ligne du DataTable est contenue dans des blocs <Categories> séparés, comme indiqué dans le fichier XML ci-dessous.

Vous pouvez télécharger les fichiers suivants à partir du Centre de téléchargement Microsoft :
Réduire cette imageAgrandir cette image
Téléchargement
Télécharger le package GetCategories.xml maintenant.
Réduire cette imageAgrandir cette image
Téléchargement
Télécharger le package WSXMLHTTP.exe maintenant. Pour plus d'informations sur la façon de télécharger des fichiers du Support technique Microsoft, cliquez sur le numéro ci-dessous pour afficher l'article correspondant dans la Base de connaissances Microsoft.
119591 Comment obtenir des fichiers de support technique Microsoft auprès des services en ligne
Microsoft a analysé ce fichier en vue de détecter la présence de virus. Microsoft a utilisé les logiciels de détection de virus les plus récents disponibles à la date de publication de ce fichier. Le fichier est conservé sur des serveurs sécurisés, empêchant toute modification non autorisée du fichier.

Pour obtenir le bloc XML qui contient ce DataTable, j'utilise le code suivant :
objNodeList = objXmlDoc.getElementsByTagName("Categories");
Il retourne un objet IXMLDOMNodeList qui contient chaque n?ud <Categories>. J'itère ensuite les éléments de cette liste à l'aide d'une boucle 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";
       
    }
Je sais déjà que chaque n?ud <Categories> aura deux n?uds dont j'ai besoin : le n?ud <ID> et le n?ud <CategoryName>. Par conséquent, la première chose que je fais est de créer un IXMLDOMNodeList et de le remplir avec les n?uds enfants du n?ud <Categories> actuel.
dataNodeList = objNodeList[i].childNodes;
J'utilise ensuite la méthode item pour accéder aux deux n?uds dont j'ai besoin pour remplir ma liste déroulante. Le premier n?ud contient le champ de base de données CategoryID et le deuxième n?ud contient le champ de base de données CategoryName. Je crée un objet Option, j'affecte au texte la valeur de CategoryName, je définie la valeur de CategoryID et je l'ajoute à la liste déroulante drpCategory. Le code qui est utilisé dans les fonctions restantes utilise la même méthode pour extraire les données nécessaires à partir de la réponse XML et pour remplir des parties de la page.

Remarque Étant donné que nous manipulons ici de petites quantités de données, l'utilisation de DOM constitue un excellent moyen d'extraire les données dont nous avons besoin. Si nous avions affaire à de grosses quantités de données, nous pourrions utiliser XSLT à la place.

Application pratique

Maintenant que j'ai couvert tous les petits détails de ce mécanisme, voyons un peu comment vous pouvez utiliser les exemples de fichiers fournis pour tirer parti de cette fonctionnalité.

Déploiement du service Web

Pour déployer le service Web ASP.NET, il vous suffit de décompresser l'exemple de service Web joint à la racine de votre serveur Web. Vous devrez ensuite ouvrir le code de DynaProducts.asmx et modifier la chaîne de connexion. Au minimum, vous devrez entrer le mot de passe SA. Après avoir apporté cette modification, recompilez le service Web.

Déploiement du fichier HTML

Le fichier HTML contient une variable nommée szUrl qui contient une URL vers le service Web. Vous trouverez cette variable dans la fonction getDataFromWS au bas de la fonction. Vous devrez la modifier et lui affecter l'URL du service Web que vous avez déployé ci-dessus.

Une fois que vous avez déployé le service Web et le fichier HTML, naviguez jusqu'au fichier HTML. Lorsqu'il se charge, la liste déroulante Category est remplie par la première demande XMLHTTP au service Web. Une fois cette liste remplie, sélectionnez une catégorie pour déclencher la demande XMLHTTP suivante qui remplit la liste déroulante Products. La sélection d'un produit dans la liste déroulante Products remplit une table avec les données relatives à ce produit.

Notez que la page n'est pas republiée durant ces demandes XMLHTTP. Là est l'avantage des demandes XMLHTTP. Si j'avais fait cela sur une grande page, elle aurait également maintenu sa position de défilement sans « clignoter » pour l'utilisateur. Impressionnant, non ?

Encore une chose : dans cet article, j'ai utilisé XMLHTTP pour interroger un service Web. J'aurais pu aussi facilement l'utiliser pour effectuer une demande de page ASPX ou de page ASP. Les possibilités d'application de cette technologie sont illimitées. J'espère que vous trouverez la technologie XMLHTTP utile lors de vos futurs développements d'applications Web.
Comme toujours, n'hésitez pas à nous envoyer vos suggestions concernant les rubriques que vous souhaiteriez voir traitées dans les futures chroniques ou dans la Base de connaissances Microsoft par le biais du formulaire Ask For It (en anglais).

Propriétés

Numéro d'article: 893659 - Dernière mise à jour: jeudi 11 mai 2006 - Version: 5.2
Les informations contenues dans cet article s'appliquent au(x) produit(s) suivant(s):
  • Microsoft ASP.NET 1.0
  • Microsoft ASP.NET 1.1
Mots-clés : 
kbgraphic kbscript kbxml kbhowto KB893659
L'INFORMATION CONTENUE DANS CE DOCUMENT EST FOURNIE PAR MICROSOFT SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE. L'UTILISATEUR ASSUME LE RISQUE DE L'UTILISATION DU CONTENU DE CE DOCUMENT. CE DOCUMENT NE PEUT ETRE REVENDU OU CEDE EN ECHANGE D'UN QUELCONQUE PROFIT.

Envoyer des commentaires

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com