.NET

27 set, 2007

Brincando com AJAX e SOAP na plataforma .NET

Publicidade

SOAP (Simple Object Access Protocol) é um protocolo simples baseado em XML que surgiu devido a necessidade de integração de sistemas web e foi definido pelo W3C. Sua utilização independe da linguagem de programação ou plataforma.

Neste artigo utilizaremos SOAP na versão 1.1 para implementarmos um exemplo prático.

SOAP

O protocolo SOAP é um elemento XML que deve possuir elementos obrigatórios e alguns elementos opcionais.

Elementos obrigatórios
  • Envelope: é a raiz da mensagem SOAP.

Exemplo:

<?xml version='1.0' encoding='utf-8'?>
<soap:Envelope
    xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    xmlns:xsd='http://www.w3.org/2001/XMLSchema'
    xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
    ...
      </soap:Envelope>
  • Body: este elemento contém a mensagem SOAP propriamente dita.

Exemplo:

<?xml version='1.0' encoding='utf-8'?>
<soap:Envelope
    xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    xmlns:xsd='http://www.w3.org/2001/XMLSchema'
    xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
    <soap:Body>
        ...
    </soap:Body>
</soap:Envelope>
Elementos opcionais:
  • Header: contém informações especificas da aplicação. Obs: O Header deve ser o primeiro elemento do Envelope.

Exemplo:


<?xml version='1.0' encoding='utf-8'?>
<soap:Envelope
    xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    xmlns:xsd='http://www.w3.org/2001/XMLSchema'
    xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
    <soap:Header>
        ...
    </soap: Header>
    <soap:Body>
        ...
    </soap:Body>
</soap:Envelope>
  • Fault: indica a ocorrência de um erro no processamento. Obs: O Fault deve estar dentro do elemento Body. O elemento Fault contém os seguintes “nós”:

faultcode – código do erro;

faultstring – descrição do erro;

faultactor – ator do erro;

detail – detalhes do erro.

Exemplo:

<?xml version='1.0' encoding='utf-8'?>
<soap:Envelope
    xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    xmlns:xsd='http://www.w3.org/2001/XMLSchema'
    xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
    <soap:Header>
        ...
    </soap: Header>
    <soap:Body>
        <soap:Fault>
            <faultcode></faultcode>
            <faultstring></faultstring>
            <faultactor></faultactor>
            <detail></detail>
        </soap:Fault>
        ...
    </soap:Body>
</soap:Envelope>

Criando WebService

Vamos criar um simples WebService para acessarmos via AJAX + SOAP. Não vou descrever todos o processo de criação de WebServices aqui, pois já o fiz no artigo “Acesso Assíncrono a WebServices na plataforma .NET – Parte II”

Criando métodos no WebService

Vamos criar um método chamado Somar que retorna uma string no formato XMLSOAP, a fim de exemplificar o Acesso Assíncrono. Segue o código da classe:

using System;
using[/cor2] System.Web;
using[/cor2] System.Collections;
using[/cor2] System.Web.Services;
using[/cor2] System.Web.Services.Protocols;
using[/cor2] System.Xml;

/// <summary>
/// Summary description for WebServiceArtigo
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebServiceArtigo : System.Web.Services.WebService
{

    public WebServiceArtigo()
    {
        //Uncomment the following line if using designed components 
        //InitializeComponent(); 
    }

    [WebMethod]
    public string HelloWorld()
    {
        return "Hello World";
    }

    [WebMethod]
    public int Somar(int[] p_arrParametros)
    {
        return p_arrParametros[0] + p_arrParametros[1];
    }
}
Como conhecer o modelo do XMLSOAP para request e response?

Existe uma forma para se saber como consumir, no caso, o método Somar do WebService criado anteriormente, basta acessar a interface do mesmo. Para isso digite o endereço local do WebService no navegador (http://localhost:1689/WebSiteArtigo/WebServiceArtigo.asmx).

A figura abaixo mostra a interface de acesso do WebService criado anteriormente:

Figura 1Figura 1

Na parte superior da interface, existe um link com o nome do seu método (Somar). Se clicarmos lá, abrir-se-á uma nova página com os modelos de consumo do método via SOAP 1.1, SOAP 1.2 e via HTTP POST. No nosso exemplo, utilizaremos apenas o modelo de consumo via SOAP 1.1.

É importante nos atentarmos para os cabeçalhos SOAPAction e Content-Type, pois os utilizaremos para realizar a requisição SOAP.

A figura abaixo representa a interface que contém os modelos de consumo dos métodos do nosso WebService:

Figura 2Figura 2

Agora nós já sabemos qual é o modelo do XMLSOAP de envio e retorno do método Somar.

JavaScript para realizar o Acesso Assíncrono

Agora colocaremos o código JavaScript utilizado para consumir o método Somar do nosso WebService. Segue o código:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Untitled Page</title>
    <script type="text/javascript">
        var NMHOST = "localhost:1689";
        var URLWEBSERVICE = "http://" + NMHOST + 
            "/WebSiteArtigo/WebServiceArtigo.asmx";

        var objXMLHttpRequest;

        function NovoXMLHttpRequest()
        {
            if(window.XMLHttpRequest) // Mozilla, Safari...
            {
                objXMLHttpRequest = new XMLHttpRequest();
            }
            else if(window.ActiveXObject) // IE
            {
                try
                {
                    objXMLHttpRequest = new 
                        ActiveXObject("Msxml2.XMLHTTP");
                }
                catch(e)
                {
                    try
                    {
                        objXMLHttpRequest = new 
                            ActiveXObject("Microsoft.XMLHTTP");
                    }
                    catch(e){}
                }
            }
        }
        
        function Somar()
        {
            NovoXMLHttpRequest();

            objXMLHttpRequest.onreadystatechange = ProcessarResposta;
            objXMLHttpRequest.open("POST", URLWEBSERVICE, true);
            objXMLHttpRequest.setRequestHeader("SOAPAction", 
                "http://tempuri.org/Somar");
            objXMLHttpRequest.setRequestHeader("Content-Type", 
                "text/xml; charset=utf-8");
            objXMLHttpRequest.send(ValoresEnvio());
        }

        function ProcessarResposta()
        {
            if(objXMLHttpRequest.readyState == 4)
            {
                if(objXMLHttpRequest.status == 200)
                {
                    var XMLDoc = objXMLHttpRequest.responseXML;

                    document.getElementById("lblResultado").innerHTML = 
                        XMLDoc.getElementsByTagName("SomarResult")[0].
                        childNodes[0].nodeValue;
                }
            }
        }

        function ValoresEnvio()
        {
            var arrParametros = new Array();
            arrParametros[0] = document.getElementById(
                "txtValor1").value;
            arrParametros[1] = document.getElementById(
                "txtValor2").value;
            
            return "<?xml version='1.0' encoding='utf-8'?>" +
                "<soap:Envelope " +
                "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " +
                "xmlns:xsd='http://www.w3.org/2001/XMLSchema' " +
                "xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>"
+
                "<soap:Body>" +
                "<Somar xmlns='http://tempuri.org/'>" +
                "<p_arrParametros>" +
                "<int>" + arrParametros[0] + "</int>" +
                "<int>" + arrParametros[1] + "</int>" +
                "</p_arrParametros>" +
                "</Somar>" +
                "</soap:Body>" +
                "</soap:Envelope>";
        }

        function RegistrarScript()
        {
            document.getElementById("btnSomar").onclick = new 
                Function("Somar();");
        }
    </script>
</head>
<body onload="RegistrarScript();">
    <form id="form1" runat="server">
    <div>
        <asp:TextBox ID="txtValor1" runat="server"></asp:TextBox>
        <asp:TextBox ID="txtValor2" runat="server"></asp:TextBox>
        <input id="btnSomar" type="button" value="Somar" /><br />
        <asp:Label ID="lblTexto" runat="server" 
            Text="Resultado:"></asp:Label>
        <asp:Label ID="lblResultado" runat="server"></asp:Label></div>
    </form>
</body>
</html>

O método JavaScript a ser chamado no nosso Acesso Assíncrono é o Somar, que é vinculado ao botão btnSomar através do método RegistrarScript que por sua vez é chamado no evento onload da tag body, conforme mostrado no código acima.

Obs: É importante enfatizar que no Acesso Assíncrono com SOAP, o método setRequestHeader do objeto XMLHttpRequest dever ser setado com pelo menos dois cabeçalhos http: SOAPAction e Content-Type. Essas informações podem ser recuperadas da interface do WebService.

Abaixo temos a representação gráfica da interface do nosso exemplo:

Figura 3Figura 3

Finalizando

Neste artigo abordamos a construção de um exemplo prático passo-a-passo de Acesso Assíncrono com SOAP.

Fica um desafio para vocês (leitores): consumir o método HelloWorld com AJAX + SOAP do WebService criado neste artigo. Na verdade é uma “tarefa de casa” (risos).

Espero ter contribuído!

Até o próximo!