Accedi con Microsoft
Accedi o crea un account.
Salve,
Seleziona un altro account.
Hai più account
Scegli l'account con cui vuoi accedere.

ASP.NET voce del supporto tecnico

Aggiornamenti dinamici delle pagine tramite XMLHTTP

Per personalizzare questa colonna in base alle proprie esigenze, è possibile invitare gli utenti a inviare idee su argomenti di proprio interesse e sui problemi che si desidera consultare negli articoli della Knowledge Base futuri e nelle colonne del Supporto vocale. È possibile inviare idee e feedback usando il modulo Ask For It. Nella parte inferiore della colonna è presente anche un collegamento alla maschera.

INTRODUZIONE

Uno dei miei modi preferiti per studiare l'usabilità delle applicazioni Web è guardare mia figlia navigare in un sito Web. Sa già bene come fare in Internet, ma sa poco degli aspetti tecnici di basso livello, che le consentono di realizzare tutti gli aspetti più interessanti.



In una sera recente, osservavo mia figlia che usava un'applicazione di e-commerce da uno dei bambini più grandi. Stava facendo il drill-down in un elenco di prodotti usando più elenchi a discesa, ognuno dei quali si nutre della selezione effettuata in precedenza. Quando ha fatto clic su un elemento in ogni elenco a discesa, la pagina è stata pubblicata nuovamente per recuperare i dati per il successivo elenco a discesa. L'esperienza è stata frustrante per lei perché la sua impressione è che la sua attività stava occupando molto tempo a causa dei post backs.



Il livello di frustrazione che stava riscontrando poteva essere facilmente alleviato dagli sviluppatori dell'applicazione se usavano solo XMLHTTP per recuperare i dati invece di pubblicare di nuovo il post. Ecco di cosa si tratta la colonna di questo mese. Ti mostrerò come usare XMLHTTP per aggiornare una parte di una pagina Web con i dati di un servizio Web microsoft ASP.NET senza eseguire un post back. Sarà davvero fantastico! Fidati di me.

Panoramica generale

XMLHTTP invia una richiesta al server Web dal client e restituisce un'isola di dati XML. A seconda della struttura del codice XML ricevuto, è possibile usare XSLT o XML DOM per modificarlo e associare parti della pagina ai dati. Si tratta di una tecnica estremamente potente.

NotaMicrosoft offre un comportamento di servizio Web per Internet Explorer che consente di effettuare chiamate asincrone ASP.NET servizi Web in modo semplice e rapido. Tuttavia, questo comportamento non è supportato e non è il modo migliore per aggiornare una pagina in modo asincrono. È invece consigliabile usare XMLHTTP.


Nell'esempio che semplimo in questa colonna, devo effettuare tre chiamate a un servizio Web ASP.NET tramite XMLHTTP. Il servizio Web esegue una query sul database Northwind nell'SQL Server locale e restituisce un DataSet al client sotto forma di diffgrammi XML. Quindi userò il modello DOM XML per analizzare i dati XML e aggiornare dinamicamente parti della pagina. Tutte queste operazioni verranno eseguite senza post.

Servizio Web

Il servizio Web che uso è denominato DynaProducts. Si tratta di un ASP.NET Web di base scritto in C# e che contiene i tre metodi seguenti.

  • GetCategories: restituisce un set di dati contenente tutte le categorie nella tabella Categories.

  • GetProducts: restituisce un set di dati contenente tutti i prodotti della categoria che sono stati passati al metodo.

  • GetProductDetails: restituisce un set di dati che contiene dettagli sul prodotto il cui IDProdotto è stato passato al metodo.

Pagina HTML

La prima cosa che può riguardare questo esempio è che la pagina che sto aggiornando, anche se il servizio Web ASP.NET non è una ASP.NET pagina. È solo una normale pagina HTML. Tuttavia, ho aggiunto alla pagina un numero equa di JavaScript sul lato client ed è quello script che effettua le chiamate al servizio Web.



Esaminiamo il primo frammento di codice della pagina 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);
}
}

Questo è il codice più grande della pagina e voglio andare su di esso in dettaglio per capire cosa succede.



All'inizio di questo blocco di script sono state create due variabili: objHttp e objXmlDoc. Si tratta delle variabili che userò per l'oggetto XMLHTTP e per l'oggetto DOM XML. Immediatamente dopo si tratta della definizione della funzione getDataFromWS. Questa è la funzione responsabile della chiamata sul lato client al servizio Web. Accetta i quattro argomenti seguenti, due dei quali sono facoltativi:

  • methodName: nome del metodo da chiamare sul servizio Web.

  • dataSetName: nome del set di dati restituito dal servizio Web.

  • wsParamValue: valore del parametro passato al servizio Web, se applicabile. (Facoltativo)

  • wsParamName: nome del parametro passato al servizio Web, se applicabile. (Facoltativo)

Suddividere la funzione getDataFromWS in parti e discuterne una per una. Ecco il primo frammento:

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

Questo blocco di codice crea l'oggetto XMLHTTP e l'oggetto Documento XML. Quindi, inizio a creare la busta 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>";

In questo codice la busta SOAP viene assegnata a una variabile stringa in modo da poterla passare al servizio Web. In realtà è piuttosto semplice individuare come formattare la busta SOAP per il servizio Web. Passare semplicemente al servizio Web e fare clic su uno dei metodi per visualizzare una busta SOAP per tale metodo. Ecco ad esempio cosa viene visualizzato quando si esplora il metodo GetCategories del servizio Web wsXMLHTTP creato per questo articolo:testo alternativoASP.NET indica come deve essere formattata la busta SOAP per un POST HTTP e un http



GET. Nell'esempio presentato in questo articolo uso HTTP POST.



Fin qui tutto bene. Vediamo ora la sezione successiva del codice.

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

}
}

Quando viene effettuata una richiesta tramite XMLHTTP, l'oggetto XMLHTTP usa una proprietà readyState per tenere traccia dello stato della richiesta. Quando tutti i dati vengono ricevuti dal servizio Web, la proprietà readyState viene impostata su un valore pari a 4. La proprietà onreadystatechange per l'oggetto XMLHTTP consente di impostare una funzione principale che verrà chiamata quando la proprietà readyState viene modificata. Assicurandomi che i dati siano stati ricevuti nella sua interezza, posso evitare di agire su di loro finché non sono pronto.



Dopo aver ricevuto tutti i dati, creo un'isola di dati XML con la risposta usando la proprietà responseText. Come è probabile che si sappia, la risposta da un servizio Web è in formato XML. In questo caso restituio un set di ADO.NET Microsoft.



La sezione successiva di questo blocco di codice usa un'istruzione switch per chiamare la funzione appropriata in base al nome del DataSet restituito dal servizio Web. Voglio accedere al codice per queste funzioni in dettaglio un po' più tardi.


Esaminiamo ora il codice che esegue effettivamente la richiesta 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);

La variabile szUrl contiene l'URL usato per chiamare il servizio Web ai fini della chiarezza. A questo punto ho un'istruzione if che indica i parametri passati come valore QueryString. Nell'ambiente in uso è possibile aggiungere i parametri all'busta SOAP. Entrambi i modi funzionano correttamente.



Il metodo open dell'oggetto XMLHTTP è chiamato next. Ho usato i primi tre argomenti per il metodo open; il metodo, l'URL e un valore booleano che specifica se la chiamata è asincrona o meno.
Importante Se si sta effettuando una chiamata asincrona così come sono qui, è necessario impostare una funzioneora tramite la proprietà onreadystatechanged.

Dopo aver impostato l'intestazione della richiesta per il tipo di contenuto, la richiesta viene inviata come busta SOAP usando la variabile stringa popolata in precedenza.



A questo punto è stato preso in controllo tutto il codice che esegue la richiesta XMLHTTP. Vediamo ora il codice che gestisce l'interfaccia nel browser e che gestisce la risposta dalla chiamata al servizio Web.

Prima di tutto, si osserva la funzione chiamata al primo caricamento della pagina.

function getCategories()
{

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

}

La prima cosa che faccio in questa funzione è creare una variabile per archiviare la firma della funzione per getDataFromWS. Lo faccio perché chiamo window.setTimeout alla fine di questa funzione per chiamare la funzione getDataFromWS. Lo scopo di questo approccio è di consentire all'utente di visualizzare lo stato in attesa del completamento della chiamata al servizio Web. Come si noterà, si sta modificando il testo interno di un DIV in modo da visualizzare un messaggio che indica che è in corso il recupero dei dati. Quindi schedule the getDataFromWS function through the window.setTimeout call, and I set it to run in one millisecond.

Elaborazione della risposta del servizio Web

Tenere presente che in precedenza è stata usata la proprietà onreadystatechanged per configurare una funzione lettore. Ricordare anche che la funzione contiene un'istruzione switch che chiama una determinata funzione in base al nome del set di dati. In questo caso, il nome del dataset è CategoriesDS. Di conseguenza, la funzione processCategory verrà chiamata dalla funzione #A0. Esaminiamo questa funzione per scoprire come usare XML DOM per analizzare la risposta dal servizio 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";

}

}

Tenere presente che la funzione getDataFromWS ha caricato i dati XML dalla risposta nell'oggetto objXmlDoc. Nella funzione processCategory se necessario, il codice XML viene analizzato per popolare l'elenco a discesa Category.



La prima cosa da fare è creare un oggetto IXMLDOMNodeList usando parte della risposta XML. Il DataSet restituito dalla chiamata al servizio Web viene restituito come diffgrammo e l'unica parte della risposta a cui si è interessati sono i dati della tabella dati inserita nel DataSet. Per ottenere questa operazione, creare un oggetto IXMLDOMNodeList dal blocco XML che contiene la tabella dati.



Se si osserva il codice del servizio Web, si scoprirà che è stata creata una tabella dati denominata Categories e aggiunta al DataSet. Quando il codice XML viene restituito dal servizio Web, il DataSet è contenuto in un blocco> <CategoriesDS e ogni riga della tabella dati è contenuta in blocchi di> separati di <Categories, come illustrato nel file XML seguente.

I file seguenti sono disponibili per il download dall'Area download Microsoft:Scaricare
scaricare GetCategories.xml pacchetto.
Scaricare scarica subito WSXMLHTTP.exe pacchetto.Per altre informazioni su come scaricare i file del supporto tecnico Microsoft, fare clic sul numero dell'articolo seguente per visualizzare l'articolo della Microsoft Knowledge Base:

119591 Come ottenere i file di supporto Microsoft dai servizi
online, Microsoft ha analizzato questo file alla ricerca di virus. Microsoft ha utilizzato il software antivirus più recente disponibile al momento della data di pubblicazione del file. Il file viene salvato su server con un livello di sicurezza avanzata che impedisce modifiche del file non autorizzate.


Per ottenere il blocco XML che contiene la tabella dati, si usa il codice seguente:

objNodeList = objXmlDoc.getElementsByTagName("Categories");

Restituisce un oggetto IXMLDOMNodeList che contiene ogni <categorie> nodo. Quindi mi rendo un'iterazione all'elenco usando un ciclo 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";

}

Si sa già che ogni <Categorie> avrà due nodi necessari: l'ID <> e il nodo <CategoryName>. Di conseguenza, la prima cosa che devo fare è creare un nuovo IXMLDOMNodeList e popolarlo con i nodi figlio del nodo <categorie> corrente.

dataNodeList = objNodeList[i].childNodes;

Quindi uso il metodo dell'elemento per accedere a entrambi i nodi che devo popolare nell'elenco a discesa. Il primo nodo contiene il campo IDCate categorie del database, il secondo contiene il campo CategoryName del database. Creare un nuovo oggetto Option, impostare il testo su CategoryName, impostare il valore su CategoryID e aggiungerlo all'elenco a discesa drpCategory. Il codice usato nelle funzioni rimanenti usa lo stesso metodo per estrarre i dati necessari dalla risposta XML e popolare parti della pagina.

Nota Quando si tratta di piccole quantità di dati, l'uso di DOM è un ottimo modo per estrarre i dati di cui abbiamo bisogno. Se si gestiscono grandi quantità di dati, è possibile scegliere di usare XSLT.

Come fare in modo che tutto funzioni

Ora che ho trattato i dettagli dettagliati del funzionamento di questa funzionalità, è il momento di illustrare come usare i file di esempio inclusi per vederlo funzionare automaticamente.

Distribuzione del servizio Web

Per distribuire il ASP.NET Web locale, è sufficiente decomprimere l'esempio del servizio Web allegato nella radice del server Web. Sarà quindi necessario aprire il codice per DynaProducts.asmx e modificare la stringa di connessione. Sarà necessario immettere almeno la password di firma di accesso condiviso. Dopo aver apportato questa modifica, ricompilare il servizio Web.

Distribuzione del file HTML

Il file HTML contiene una variabile denominata szUrl che contiene un URL del servizio Web. Questa variabile si trova nella funzione getDataFromWS nella parte inferiore della funzione. Sarà necessario modificare questo valore nell'URL del servizio Web distribuito in precedenza.


Dopo aver distribuito sia il servizio Web che il file HTML, passare al file HTML. Al caricamento, l'elenco a discesa Categoria viene popolato con la prima richiesta XMLHTTP al servizio Web. Una volta popolata, selezionare una categoria per avviare la successiva richiesta XMLHTTP che popola l'elenco a discesa Prodotti. Se si seleziona un prodotto dall'elenco a discesa Prodotti, viene popolata una tabella con i dati sul prodotto.



Si noti che la pagina non esegue il post back durante una di queste richieste XMLHTTP. Questo è il vantaggio delle richieste XMLHTTP. Se avessi eseguito questa operazione su una pagina di grandi dimensioni, la pagina avrebbe mantenuto anche la posizione di scorrimento senza lampeggiare all'utente. Se me lo chiedi, sono alcune cose davvero potenti.



Un'altra cosa: in questo articolo è stato usato XMLHTTP per eseguire query su un servizio Web. Sarebbe stato così facile da usare per richiedere una pagina ASPX o una pagina ASP. Le possibilità per usare questa tecnologia sono infinite. Mi auguriamo che XMLHTTP sia utile per lo sviluppo futuro di applicazioni Web.

Come sempre, è possibile inviare idee su argomenti da affrontare nelle colonne future o nella Microsoft Knowledge Base usando il modulo Ask For It.

Serve aiuto?

Vuoi altre opzioni?

Esplorare i vantaggi dell'abbonamento e i corsi di formazione, scoprire come proteggere il dispositivo e molto altro ancora.

Le community aiutano a porre e a rispondere alle domande, a fornire feedback e ad ascoltare gli esperti con approfondite conoscenze.

Queste informazioni sono risultate utili?

Come valuti la qualità della lingua?
Cosa ha influito sulla tua esperienza?
Premendo Inviare, il tuo feedback verrà usato per migliorare i prodotti e i servizi Microsoft. L'amministratore IT potrà raccogliere questi dati. Informativa sulla privacy.

Grazie per il feedback!

×