Entrar com a conta da Microsoft
Entrar ou criar uma conta.
Olá,
Selecionar uma conta diferente.
Você tem várias contas
Escolha a conta com a qual você deseja entrar.

ASP.NET coluna Suporte de Voz

Atualizações de página dinâmicas usando XMLHTTP

Para personalizar esta coluna de acordo com suas necessidades, queremos convidá-lo a enviar suas ideias sobre tópicos de seu interesse e problemas que você deseja ver abordados em futuros artigos da Base de Dados de Conhecimento e colunas de Voz de Suporte. Você pode enviar suas ideias e comentários usando o formulário Solicitar. Também há um link para o formulário na parte inferior desta coluna.

INTRODUÇÃO

Uma das minhas maneiras favoritas de estudar a usabilidade do aplicativo Web é ver minha esposa navegar por um site. Ela pode se sair muito bem na Internet, mas sabe pouco sobre os aspectos técnicos de baixo nível (o que ela chama de "coisas entediantes") que fazem tudo funcionar.



Em uma noite recente, eu estava assistindo à minha esposa usar um aplicativo de comércio eletrônico de um dos grandões. Ela estava detalhando uma listagem de produtos usando várias listas, cada uma delas se alimentando da seleção feita anteriormente. Conforme ela clicava em um item em cada lista drop-down, a página postada de volta para obter dados para a próxima lista. A experiência foi frustrante para ela porque sua impressão era de que estava demorando muito devido aos backs da postagem.



O nível de frustração que ela estava enfrentando poderia ter sido facilmente facilitado pelos desenvolvedores do aplicativo se eles só usaram XMLHTTP para recuperar os dados em vez de postar de volta. É sobre isso que se trata a coluna deste mês. Mostrarei como usar XMLHTTP para atualizar uma parte de uma página da Web com dados de um serviço Web do Microsoft ASP.NET sem fazer uma postagem de volta. Isso vai ser muito legal! Confie em mim.

Visão geral

XMLHTTP funciona enviando uma solicitação para o servidor Web do cliente e retornando uma ilha de dados XML. Dependendo da estrutura do XML recebido, você pode usar o XSLT ou o XML DOM para manipulá-lo e vincular partes da página a esses dados. Essa é uma técnica extremamente poderosa.

O NoteMicrosoft oferece um comportamento de Serviço Web para o Internet Explorer que torna as chamadas assíncronas para ASP.NET Serviços Web rápidas e fáceis. No entanto, esse comportamento não é suportado e não é a melhor maneira de atualizar uma página assíncrona. Em vez disso, você deve usar XMLHTTP!


No exemplo que trabalharei nesta coluna, vou fazer três chamadas de serviço Web para um serviço ASP.NET Web por meio de XMLHTTP. O serviço Web consultará o banco de dados da Northwind no SQL Server local e retornará um DataSet ao cliente na forma de um diffgram XML. Em seguida, vou usar o XML DOM para analisar esses dados XML e atualizar dinamicamente partes da minha página. Tudo isso será feito sem uma postagem de volta.

O serviço Web

O serviço Web que vou usar é denominado DynaProducts. Trata-se de um ASP.NET Web que é escrito em C# e que contém os três métodos a seguir.

  • GetCategories – retorna um DataSet que contém todas as categorias na tabela Categorias.

  • GetProducts – retorna um DataSet que contém todos os produtos da categoria que são passados para o método.

  • GetProductDetails – retorna um DataSet que contém detalhes sobre o produto cujo IDProduto é passado para o método.

A página HTML

A primeira coisa que pode parecer interessante sobre esse exemplo é que a página que estou atualizando, embora o serviço Web ASP.NET não seja uma página ASP.NET página. É apenas uma página HTML normal. No entanto, adicionei uma quantidade justa de JavaScript do lado do cliente à página, e é esse script que faz as chamadas para o serviço Web.



Vamos ver o primeiro trecho de código da página 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);
}
}

Esta é a maior parte do código da página e quero ver isso em detalhes para que você entenda o que está acontecendo.



Na parte superior desse bloco de script, criei duas variáveis: objHttp e objXmlDoc. Estas são as variáveis que vou usar para meu objeto XMLHTTP e meu objeto XML DOM. Imediatamente depois disso, é a definição da função getDataFromWS. Essa é a função que é responsável por fazer a chamada no lado do cliente para o serviço Web. São necessários os quatro argumentos a seguir, dois dos quais são opcionais:

  • nomedome – o nome do método para chamar no serviço Web.

  • DataSetName – O nome do DataSet que é retornado pelo serviço Web.

  • wsParamValue – o valor do parâmetro que é passado para o serviço Web, se aplicável. (Opcional)

  • wsParamName – O nome do parâmetro que é passado para o serviço Web, se aplicável. (Opcional)

Vamos separar a função getDataFromWS em partes e discutir cada uma delas. Este é o primeiro trecho:

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

Esse bloco de código cria o objeto XMLHTTP e o objeto Documento XML. Em seguida, começo a criar o envelope 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>";

Neste código, estou atribuindo o envelope SOAP a uma variável de cadeia de caracteres para que eu possa passá-lo para o serviço Web. Na verdade, é muito fácil descobrir como formatar o envelope SOAP para seu serviço Web. Basta navegar até o serviço Web e clicar em um dos métodos para ver um envelope SOAP desse método. Por exemplo, veja o que vejo ao navegar para o método GetCategories do serviço Web wsXMLHTTP que criei para este artigo: o texto alternativoASP.NET informa como o envelope SOAP deve ser formatado para uma POSTAGEM HTTP e

um HTTP

GET. No exemplo apresentado neste artigo, vou usar HTTP POST.



Até aqui, tudo bem. Agora, vamos ver a próxima seção do código.

// 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 uma solicitação é feita por meio de XMLHTTP, o objeto XMLHTTP usa uma propriedade readyState para controlar o status da solicitação. Quando todos os dados são recebidos de volta do serviço Web, a propriedade readyState muda para um valor de 4. A propriedade onreadystatechange para o objeto XMLHTTP permite configurar uma função de retorno de chamada que será chamada quando a propriedade readyState mudar. Ao garantir que os dados foram recebidos em sua totalidade, posso evitar agir sobre esses dados até que eu esteja pronto.



Depois que todos os dados são recebidos, eu crio uma ilha de dados XML com a resposta usando a propriedade responseText. Como você provavelmente sabe, a resposta de um serviço Web está em formato XML. Nesse caso, estou retornando um Microsoft ADO.NET DataSet.



A próxima seção deste bloco de código usa uma instrução de opção para chamar a função apropriada com base no nome do DataSet retornado do serviço Web. Entrarei no código dessas funções em detalhes um pouco mais tarde.


Agora, vamos ver o código que realmente executa a solicitação 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);

A variável szUrl contém a URL que é usada para chamar o serviço Web para o bem da clareza. Em seguida, tenho uma instrução se que aborda todos os parâmetros que são passados como um valor QueryString. Em seu ambiente, talvez você queira adicionar os parâmetros ao envelope SOAP. De qualquer forma, funcionará muito bem.



O método aberto do objeto XMLHTTP é chamado de próximo. Usei os três primeiros argumentos para o método aberto; o método, a URL e um valor boolano que especifica se a chamada é assíncrona ou não.
Importante Se você estiver fazendo uma chamada assíncrona como eu estou aqui, deverá configurar uma função de retorno de chamada por meio da propriedade onreadystatechanged.

Depois que o título da solicitação para o tipo de conteúdo for definido, enviarei a solicitação como um envelope SOAP usando a variável de cadeia de caracteres preenchida anteriormente.



Agora, já falamos sobre todo o código que faz a solicitação XMLHTTP. Agora vamos dar uma olhada no código que lida com a interface no navegador e que lida com a resposta da chamada de serviço web.

Primeiro, vamos ver a função que é chamada quando a página é carregada pela primeira vez.

function getCategories()
{

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

}

A primeira coisa que eu faço nesta função é criar uma variável para armazenar a assinatura da função para obterDataFromWS. Faço isso porque vou chamar window.setTimeout no final desta função para chamar a função getDataFromWS. A finalidade dessa abordagem é permitir que eu exibir o status para o usuário enquanto aguarda a conclusão da chamada do serviço Web. Observe que estou alterando o texto interno de uma DIV para exibir uma mensagem indicando que os dados estão sendo recuperados. Em seguida, agendo a função getDataFromWS por meio da chamada window.setTimeout e a defini para ser executado em um milissegundo.

Processar a resposta do serviço Web

Lembre-se anteriormente de que usei a propriedade onreadystatechanged para configurar uma função callback. Lembre-se também de que a função retorno de chamada contém uma instrução de opção que chama uma função específica com base no nome do DataSet. Nesse caso, nosso nome de Conjuntos de Dados é CategoriesDS. Portanto, a função processCategory será chamada a partir da função callback. Vamos dar uma olhada nessa função para ver como usar o XML DOM para analisar a resposta do serviço 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";

}

}

Lembre-se de que a função getDataFromWS carregou XML da resposta para o objeto objXmlDoc. Na função ProcessCategory, faço o xml e o analisarei para preencher o drop-down Categoria.



A primeira coisa que eu faço é criar um objeto IXMLDOMNodeList usando parte da resposta XML. O DataSet que estou retornando da chamada de serviço Web é retornado como um difgrama, e a única parte dessa resposta em que estou realmente interessado são os dados da Tabela de Dados que inseri no Conjuntos de Dados. Posso chegar a isso criando um objeto IXMLDOMNodeList a partir do bloco XML que contém a Tabela de Dados.



Se você olhar para o código do serviço Web, verá que eu criarei uma Tabela de Dados que se chama Categorias e adicioná-la ao Conjuntos de Dados. Quando o XML é retornado do serviço Web, o Conjuntos de Dados está contido em um bloco> CategoriesDS do <, e cada linha da Tabela de Dados está contida em blocos <Categorias> separados, conforme mostrado no arquivo XML abaixo.

Os arquivos a seguir estão disponíveis para download no Centro de Download da Microsoft:
Baixar baixar o pacote GetCategories.xml agora.
Baixar baixar o pacote WSXMLHTTP.exe agora.Para obter mais informações sobre como baixar arquivos do Suporte da Microsoft, clique no seguinte número do artigo para exibir o artigo na Base de Dados de Conhecimento da Microsoft:

119591 Como obter arquivos de suporte da Microsoft de serviços online a
Microsoft digitalizava esse arquivo em busca de vírus. A Microsoft utilizou o software de detecção de vírus mais recente disponível na data em que o arquivo foi postado. O arquivo está armazenado em servidores de segurança avançada que ajudam a evitar alterações não autorizadas nele.


Para obter o bloco XML que contém essa Tabela de Dados, uso o seguinte código:

objNodeList = objXmlDoc.getElementsByTagName("Categories");

Isso retorna um objeto IXMLDOMNodeList que contém cada nó <Categorias> nó. Em seguida, im itero por essa lista usando um loop para.

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

}

Já sei que cada nó <Categorias> terá dois nós de que preciso: o nó> <ID do <e o nó <> CategoryName. Portanto, a primeira coisa que eu faço é criar um novo IXMLDOMNodeList e preencha-o com os nós filho do nó <Categorias> atual.

dataNodeList = objNodeList[i].childNodes;

Em seguida, uso o método de item para acessar os dois nós que preciso para preencher minha lista. O primeiro nó contém o campo ID de Categoria do banco de dados e o segundo nó contém o campo Nomeda Categoria do banco de dados. Criar um novo objeto Option, definir o texto como Nomecategoria, definir o valor como IDcategoria e adicioná-lo à lista de opções drpCategory. O código usado nas funções restantes usa o mesmo método para retirar os dados necessários da resposta XML e preencher partes da página.

Observe que, como estamos lidando com pequenas quantidades de dados aqui, usar o DOM é uma ótima maneira de retirar os dados de que precisamos. Se você estava lidando com uma grande quantidade de dados, pode optar por usar xSLT.

Como fazer tudo funcionar

Agora que já cobrei os detalhes de como tudo isso funciona, é hora de ver como você pode usar os arquivos de exemplo incluídos para vê-los funcionarem para si mesmo.

Implantando o serviço Web

Para implantar o ASP.NET Web, basta descompague a amostra de serviço Web anexada para a raiz do seu servidor Web. Em seguida, será necessário abrir o código de DynaProducts.asmx e alterar a cadeia de conexão. No mínimo, você precisará inserir a senha do SA. Depois de fazer essa alteração, recompile o serviço Web.

Implantando o arquivo HTML

O arquivo HTML contém uma variável chamada szUrl que contém uma URL para o serviço Web. Você encontrará essa variável na função getDataFromWS, na parte inferior da função. Você precisará alterá-la para a URL do serviço Web implantado acima.


Depois de implantar o serviço Web e o arquivo HTML, navegue até o arquivo HTML. Quando ele for carregado, a lista listada categoria será preenchida pela primeira solicitação XMLHTTP para o serviço Web. Depois que isso tiver sido preenchido, selecione uma categoria para dar início à próxima solicitação XMLHTTP que preencha a lista de produtos. Selecionar um produto na lista lista de Produtos preencherá uma tabela com dados sobre esse produto.



Observe que a página não é postada de volta durante nenhuma dessas solicitações XMLHTTP. Essa é a beleza das solicitações XMLHTTP. Se eu tivesse feito isso em uma página grande, a página também teria mantido sua posição de rolagem sem "piscar" para o usuário. Se você me perguntar, isso é muito poderoso!



Mais uma coisa: neste artigo, usei XMLHTTP para consultar um serviço Web. Eu poderia ter usado facilmente para fazer uma solicitação de uma página ASPX ou uma página ASP. As possibilidades de como você pode colocar essa tecnologia em uso são infinitas. Espero que você ache XMLHTTP útil no desenvolvimento futuro de aplicativos Web.

Como sempre, sinta-se à vontade para enviar ideias sobre tópicos que você deseja abordar em colunas futuras ou na Base de Dados de Conhecimento da Microsoft usando o formulário Solicitar.

Precisa de mais ajuda?

Quer mais opções

Explore os benefícios da assinatura, procure cursos de treinamento, saiba como proteger seu dispositivo e muito mais.

As comunidades ajudam você a fazer e responder perguntas, fazer comentários e ouvir especialistas com conhecimento avançado.

Essas informações foram úteis?

Qual é o seu grau de satisfação com a qualidade do idioma?
O que afetou sua experiência?
Ao pressionar enviar, seus comentários serão usados para aprimorar os produtos e serviços da Microsoft. Seu administrador de TI poderá coletar esses dados. Política de Privacidade.

Agradecemos seus comentários!

×