Consumindo um webservice ASP.NET com Jquery/JSON.

Vamos começar analisando o lado do servidor, quando você consulta um WebService ASP.NET, obtém como resposta um documento XML. Para quem já utilizou o JSON sabe que além de ser mais leve, ele também é muito mais fácil de trabalhar no lado do cliente (javascript). Isso acontece por que quando o JSON é consumido pelo javascript, ele é automaticamente transformado em um objeto, assim podemos acessar as propriedades dele diretamente, sem a necessidade de navegar pelo XML. Com o lançamento do ASP.NET AJAX foi incluída a capacidade do webservice responder JSON, só que para isso é necessário fazer algumas configurações, e é sobre elas que vou falar neste artigo.

Quem já está utilizando o framework 3.5 pode ir direto para a criação do WebService.

Quem ainda está utilizando o framework 2.0, é necessário fazer a instalação do ASP.NET AJAX Extensions 1.0. Depois de instalado você terá que mudar o seu web.config, ou, ao criar o Web Site definir o template como “ASP.NET AJAX-Enabled Web Site”. Se você escolher esta opção não precisará fazer nenhuma alteração no web.config, se você já tem um projeto criado e quer acrescentar a funcionalidade nele, deverá fazer as alterações descritas neste exemplo do web.config com comentários ou copiar o exemplo abaixo:

web.config (para o frameword 2.0):

<?xml version="1.0"?>
<configuration>
  <configSections>
    <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
      <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
          <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
        <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
          <section name="JSONSerialization" type="System.Web.Configuration.ScriptingJSONSerializationSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" />
          <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
          <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
        </sectionGroup>
      </sectionGroup>
    </sectionGroup>
  </configSections>

  <system.web>
    <pages>
      <controls>
        <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </controls>
    </pages>
    <!--
          Set compilation debug="true" to insert debugging
          symbols into the compiled page. Because this
          affects performance, set this value to true only
          during development.
    -->
    <compilation debug="false">
      <assemblies>
        <add assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </assemblies>
    </compilation>

    <httpHandlers>
      <remove verb="*" path="*.asmx"/>
      <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
    </httpHandlers>

    <httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </httpModules>
  </system.web>

  <system.web.extensions>
    <scripting>
      <webServices>
      <!-- Uncomment this line to customize maxJSONLength and add a custom converter -->
      <!--
      <JSONSerialization maxJSONLength="500">
        <converters>
          <add name="ConvertMe" type="Acme.SubAcme.ConvertMeTypeConverter"/>
        </converters>
      </JSONSerialization>
      -->
      <!-- Uncomment this line to enable the authentication service. Include requireSSL="true" if appropriate. -->
      <!--
        <authenticationService enabled="true" requireSSL = "true|false"/>
      -->

      <!-- Uncomment these lines to enable the profile service. To allow profile properties to be retrieved
           and modified in ASP.NET AJAX applications, you need to add each property name to the readAccessProperties and
           writeAccessProperties attributes. -->
      <!--
      <profileService enabled="true"
                      readAccessProperties="propertyname1,propertyname2"
                      writeAccessProperties="propertyname1,propertyname2" />
      -->
      </webServices>
      <!--
      <scriptResourceHandler enableCompression="true" enableCaching="true" />
      -->
    </scripting>
  </system.web.extensions>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules>
      <add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </modules>
    <handlers>
      <remove name="WebServiceHandlerFactory-Integrated" />
      <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode"
           type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode"
           type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </handlers>
  </system.webServer>
</configuration>

Agora você deve incluir um novo WebService no seu projeto, para seguir o exemplo utilize o nome WebService.asmx. Agora vamos defini-lo como um ScriptService que contém ScriptMethods, para isso você deverá:

  • incluir a referência para o namespace System.Web.Script.Services.
  • adicionar o atributo ScriptService na classe do WebService.
  • adicionar o atributo ScriptMethod(ResponseFormat=ResponseFormat.JSON) no método.

Veja o código do webService.cs abaixo:

using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;

/// <summary>
/// Summary description for WebService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class WebService : System.Web.Services.WebService {
    [WebMethod]
    [ScriptMethod(ResponseFormat=ResponseFormat.Json)]
     public string HelloWorld() {
        return "Hello World";
    }
}

O seu WebService já está preparado para responder JSON, só que não adianta abrir o browser e testar, se você fizer isto terá como resposta um documento XML, isso acontece porque para ele devolver uma resposta do tipo JSON, ele deve receber uma requisição com o “content-type=’JSON’”, senão ele devolve XML, então para testar teremos que fazer uma requisição via javascript, para fazer este teste será necessário baixar a última versão do Jquery, e um plugin (que ainda está em construção mas já funciona) que fará a chamada do webservice. Coloque estes dois arquivos na mesma pasta e não esqueça de fazer a referência no HTML.

Adicione um novo arquivo chamado JqueryComWs.aspx e copie o código abaixo:

<!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 runat="server">
    <title>Consulta um webService</title>
    <script src="jquery-1.2.3.js" type="text/javascript"></script>
    <script src="jquery.ws.js" type="text/javascript"></script>
    <script src="meuscript.js" type="text/javascript"></script>

</head>
<body>
    <form id="form1" runat="server">
    <button id="btnHelloWorld">Helo World</button>
    <div>

    </div>
    </form>
</body>
</html>

Criar o arquivo meuscript.js na mesma pasta do arquivo aspx e digitar o código a seguir:

//Utilizando e evento de carregamento da página
$(document).ready(function(){
    //Ao clicar no botão btnHelloWorld
    $("#btnHelloWorld").click(function(){
        //Chame o WebService
        $.ws("WebService.asmx/HelloWorld",retorno);
    });
});

function retorno(JSON){
    alert(JSON);
    //para o framework 3.5 troque a linha de cima pela linha abaixo,
    //quando o webservice retorna string o parser cria um objeto "d".
    //alert(JSON.d);
}

Ao executar a página você verá que a página faz a consulta ao WebService e trás a informação que queremos, o “Hello World”.

Vamos partir para um exemplo mais complexo, passando parâmetro para o WebService
Parece que tudo está certo e terminado? Não fique tão animado! Ainda faltam algumas considerações, este teste que fizemos não passa nenhum parâmetro para o webservice, se você tentar passar parâmetro no padrão do jquery ({’chave’:'valor’,'chave’:'valor’} ou “chave=valor&chave=valor”) utilizando o “method=post” irá receber o erro “JSON primitive invalid”, isto ocorre porque (felizmente) o webservice está esperando uma string no padrão JSON, e não alguns pares de chave e valor, e é isso que o jquery passa para o webservice quando passamos parâmetros para a função ajax. Para resolver isso é só criar uma string no formato JSON e passar para ela como um único parâmetro.

Para quem ainda não percebeu, isto é muito bom, porque é possível fazer o mesmo que uma requisição soap comum, ou seja, passar objetos complexos como arrays. Vamos fazer um teste, primeiro vamos criar um novo WebService com o nome WebService2.asxm com 2 métodos:

  • WebService2
  • o getPessoas que retornará uma coleção de pessoas
  • o setPessoasEscolhidas que receberá um array com os identificadores das pessoas que foram escolhidas e retornará o número de pessoas que foram escolhidas

A intenção deste exemplo é mostrar que podemos receber e enviar tipos complexos como um objeto, um array ou um array de objetos.

using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Collections.ObjectModel;
using System.Web.Script.Services;

/// <summary>
/// Definindo uma classe pessoa, para demonstrar o retorno de um objeto complexo.
/// </summary>
public class Pessoa
{
    //Construtor
    public Pessoa(){}
    public Pessoa(int Id, string Nome)
    {
        this.Nome = Nome;
        this.Id = Id;
    }
    //propriedades
    public int Id;
    public string Nome;

}

/// <summary>
/// WebService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService] //aqui estamos definindo que o WebService irá se comportar como um ScriptService
public class WebService2 : System.Web.Services.WebService {
    //declarando uma propriedade privada para conter o objeto pessoas,
    //isto está sendo feito para não acessarmos um banco de dados,
    //que tornaria o exemplo mais complexo que o necessário.
    private Collection<Pessoa> pessoas;

    //método construtor do WebService, iremos utilizar ele para carregar os valores
    public WebService2 () {
       this.pessoas = new Collection<Pessoa>();
        pessoas.Add(new Pessoa(1, "Victor"));
        pessoas.Add(new Pessoa(2, "Mariana"));
        pessoas.Add(new Pessoa(3, "Valdir"));
        pessoas.Add(new Pessoa(4, "Valmir"));
        pessoas.Add(new Pessoa(5, "Alan"));
        pessoas.Add(new Pessoa(6, "Venceslau"));
        pessoas.Add(new Pessoa(7, "Daniel"));
    }

    [WebMethod]
    //definindo que WebMethod irá se comportar como um ScriptMethod que retorna JSON
    [ScriptMethod(ResponseFormat=ResponseFormat.Json)]
    public Collection<Pessoa> getPessoas() {
        //retornando o objeto pessoas que foi carregado no construtor do WebService
        return pessoas;
    }
    [WebMethod]
    //definindo que WebMethod irá se comportar como um ScriptMethod que retorna JSON
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public string setPessoasEscolhidas(int[] idPessoas)
    {
        //retornando número de pessoas que foi passdo no array idPessoas.
        return "Recebi " + idPessoas.Length + " pessoa(s).";
    }

}

Agora vamos alterar a página e o javascript para que ele passe os parâmetros corretamente:

Arquivo JqueryComWs.aspx:

<!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>Consulta um webService</title>
    <script src="jquery-1.2.3.js" type="text/javascript"></script>
    <script src="jquery.ws.js" type="text/javascript"></script>
    <script src="meuscript.js" type="text/javascript"></script>

</head>
<body>
    <form id="form1" runat="server">
    <button id="btnHelloWorld">Helo World</button>
    <div>
        <!--Definindo novos elementos que serão utilizados pelo javascript-->
        <button id="carregarPessoas">Carregar</button>
        <fieldset id="pessoas">
           <button id="enviaPessoas">Envia</button>
        </fieldset>
        <!--Fim das alterações-->
    </div>
    </form>
</body>
</html>

Arquivo meuscrip.js

//Utilizando e evento de carregamento da página
$(document).ready(function(){
    //Ao clicar no botão btnHelloWorld
    $("#btnHelloWorld").click(function(){
        //Chamar o WebService
        $.ws("WebService.asmx/HelloWorld",retorno);
        //é utilizado para o formulário não dar um post
        return false;
    });
    //vamos esconder o fieldset que irá conter as pessoas
    $("#pessoas").hide();
    //adicionando uma função ao evento click do botão carregarPessoas
    $("#carregarPessoas").click(function(){
        //chamando o método getPessoas do WebService2.asmx, quando terminar irá chamar a função retornoPessoas
        $.ws("WebService2.asmx/getPessoas",retornoPessoas);
        //é utilizado para o formulário não dar um post
        return false;
    })
    //adicionando uma função ao evento click do botão enviaPessoas
    $("#enviaPessoas").click(function(){
        //criando um array
        var intPessoas = new Array()
        //Para cada item checado dentro do fildset pessoas
        $("#pessoas :checked").each(function(i){
            //adicione o valor no array intPessoas
            intPessoas[i] = $(this).val();
        });
        //criando a string JSON que será passada como parrâmetro para o método
        //ele deverá ficar parecido com {'idPessoas':[1,4,6,8]}onde o idPessoas é o
        //nome do parâmetro e o [1,4,6,8] é o array no formato JSON
        var strPessoas ="{'idPessoas':["+intPessoas.join(",")+"]}";
        //chamando o método setPessoasEscolhidas do WebService2.asmx, quando terminar
        //irá chamar a função retornoEnviaPessoas, ele está passando como parâmetro a strPessoas
        $.ws("WebService2.asmx/setPessoasEscolhidas",retornoEnviaPessoas,strPe ssoas);
        //é utilizado para o formulário não dar um post
        return false;
    });
});

//função de retorno
function retorno(JSON){
    //dá um alert do conteúdo retornado
    //no framework 3.5 troque o JSON por JSON.d
    alert(JSON);
}

//função de retorno que exibirá as pessoas
function retornoPessoas(JSON){
    //Exibe o fieldset pessoas
    $("#pessoas").show();
    //para cada objeto retornado no JSON
    //no framework 3.5 troque o JSON por JSON.d
    $(JSON).each(function(i){
        //adione um checkbox dentro do fieldset pessoas
        $("#pessoas").prepend("<input type='checkbox' value='"+this.Id+"' id='chk_"+i+"' name='pessoa' /><label for='chk_"+i+"'> "+this.Nome+"</label><br />")
    });
}
//função de retorno que exibirá a quantidade de pessoas enviadas para o webservice
function retornoEnviaPessoas(JSON){
    //dá um alert do conteúdo retornado
    //no framework 3.5 troque o JSON por JSON.d
    alert(JSON);
}
Conclusão

Para quem precisa consumir um webservice ASP.NET com javascript e não quer utilizar a parte cliente do AJAX.NET o Jquery é uma ótima alternativa, não é necessário fazer muita coisa para deixar ele funcionando em perfeita harmonia com o .NET.

Downloads:

Uma resposta para “Consumindo um webservice ASP.NET com Jquery/JSON.”

  1. Fábio Margarito Falou:

    Tudo bem cara?

    Ótimo artigo. Simples, rápido e objetivo. Manda para .net Magazine. Este tipo de conhecimento é legal ser compartilhado.

    Parabéns

Deixe uma resposta

Busca

Arquivos

Categorias

Meta

Estilos

Copyright - 2002-2005 - Victor Cavalcante