Servicios WCF con AJAX y JSON.

Un tema sencillo pero que aún mucho programadores desconocen o no saben bien como implementar es la forma de exponer un servicio WCF para ser ejecutado vía AJAX y devolviendo los datos en formato JSON. Vamos a ver un ejemplo de como hacerlo, utilizando un servicio simple de WCF y jQuery desde una página HTML.

Lo primero que debemos hacer es crear un nuevo servicio, desde la plantilla “WCF Service with AJAX enabled”.

image

Al seleccionar este tipo de plantilla se crean los ficheros del servicio (*.svc y *.svc.cs) y el archivo de configuración, web.config. También añadiremos a nuestro proyecto una página simple HTML para probar el servicio (el contenido de todos estos ficheros los veremos más adelante).

image

Es importante destacar que en el archivo de configuración se crea un endpoint a nuestro servicio y un comportamiento (behaviour) que permitirá su ejecución con AJAX, esto se indica con enableWebScript. Sin esta opción el servicio no permitirá su ejecución con AJAX.

<system.serviceModel>
    <behaviors>
        <endpointBehaviors>
            <behavior name="WebApplication1.MyServiceSampeAspNetAjaxBehavior">
                <enableWebScript />
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
        multipleSiteBindingsEnabled="true" />
    <services>
        <service name="WebApplication1.MyServiceSampe">
            <endpoint address="" behaviorConfiguration="WebApplication1.MyServiceSampeAspNetAjaxBehavior"
                binding="webHttpBinding" contract="WebApplication1.MyServiceSampe" />
        </service>
    </services>
</system.serviceModel>

Ahora creamos el servicio, que es extremadamente simple: tan solo un método en el que devolvemos una nueva instancia de la clase Foo.

Un aspecto a destacar es que utilizamos la configuración simplificada de WCF por lo que no es necesario tener una interfaz adicional sobre el servicio.

El código también incluye la clase Foo – que es el tipo de dato que queremos devolver en JSON - , recordad que es necesario decorar la clase con los atributos DataContract y DataMember.

using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;

namespace WebApplication1
{
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class MyServiceSampe
    {        
        [OperationContract]
        public Foo GetFoo()
        {
            return new Foo() { Id = Guid.NewGuid(), Name= "devjoker", Surname="devjoker.com" };
        }        
    }

    [DataContract]
    public class Foo
    {
        [DataMember]
        public Guid Id { get; set; }
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string Surname { get; set; }
    }

}

En la página de prueba que hemos creado, añadimos una referencia a jQuery y realizamos la llamada al servicio. El callback de dicha llamada recibe los datos obtenidos del servicio y los muestra en pantalla.

<!DOCTYPE html>
<!--ServiceClientPage.html-->
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
  <meta charset="utf-8">
  <title>devjoker.com</title>
  <script>
      $(document).ready(function () {
          $.post("MyServiceSampe.svc/GetFoo", function (response) {
              var foo = response.d;
              $("#foo_id").val(foo.Id);
              $("#foo_name").val(foo.Name);
              $("#foo_surname").val(foo.Surname);
          });
      });

  </script>
</head>
    <body>
        <h1>Service Client Sample</h1>
        <h2>www.devjoker.com</h2>
        <div id="content">
            <input type="text" id="foo_id"/>
            <input type="text" id="foo_name"/>
            <input type="text" id="foo_surname"/>
        </div>
    </body>
</html>

La ejecución de la página tiene el siguiente aspecto, nada del otro mundo!

image

Si nos fijamos en el código cliente, observamos que el resultado del servicio lo obtenemos a través de una propiedad “d” de la respuesta:

var foo = response.d;

Por defecto, WCF devuelve los datos envueltos en un propiedad «d», este comportamiento es debido a una recomendación de seguridad, como se explica en este enlace. Si analizamos el tráfico HTTP vemos claramente este comportamiento.

image

No obstante, esto suele ser interpretado como un inconveniente por muchos desarrolladores. Por supuesto es posible devolver el resultado de forma plana modificando el archivo de configuración del siguiente modo:

<behaviors>
    <endpointBehaviors>
        <behavior name="WebApplication1.MyServiceSampeAspNetAjaxBehavior">
            <enableWebScript />
            <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="WrappedRequest" /> 
        </behavior>
    </endpointBehaviors>
</behaviors>

Nota: Es posible configurar el servicio del mismo modo, utilizando los atributos WebInvoke y WebGet, aunque personalmente prefiero este acercamiento desacoplado, ya que es posible modificar como envía y devuelve datos el servcio desde configuración.

Si modificamos el web.config de este modo obtenemos la respuesta limpia.

image

Para que el ejemplo funcione debemos modificar también el código javascript cliente, ya no es necesario leer la propiedad «d»

$(document).ready(function () {
    $.post("MyServiceSampe.svc/GetFoo",  function (response) {
        // var foo = response.d
        var foo = response;
        $("#foo_id").val(foo.Id);
        $("#foo_name").val(foo.Name);
        $("#foo_surname").val(foo.Surname);
    });
});

Enviar parámetros al servicio WCF

Ahora vamos a ver otro ejemplo, esta vez enviado parámetros al servicio. Lo primero añadimos un nuevo método al servicio, en el que enviamos dos parámetros.

[OperationContract]        
public Foo BuildFoo(string name, string surname)
{
    return new Foo() { Id = Guid.NewGuid(), Name = name, Surname = surname };
}

El código cliente para ejecutar el servicio es ligeramente mas complejo, aunque nada del otro mundo:

$.ajax({
    url: "MyServiceSampe.svc/BuildFoo",
    type: "POST",
    data: JSON.stringify( { name: "The name", surname: "The surname" }),              
    contentType: "application/json"
}, function (response) {
        var foo = response;
        $("#foo_id").val(foo.Id);
        $("#foo_name").val(foo.Name);
        $("#foo_surname").val(foo.Surname);
});

Lo único destacable es el uso de $.ajax y la función JSON.stringify para el envío de los parámetros al servicio. No olvidemos especificar el contentType “application/json”.

Por último, vamos a añadir otro método al servicio, está vez recibiendo como parámetro una clase .net InputType .
[OperationContract]        
public Foo BuildFooFromType(InputType input)
{
    return new Foo() { Id = Guid.NewGuid(), Name = input.Name, Surname = input.Surname };
}

Donde el parámetro “input” de entrada es la siguiente clase:

public class InputType {    
    public string Name { get; set; }    
    public string Surname { get; set; }
}

Y la ejecución del lado cliente es muy similar al ejemplo anterior, pero debemos “envolver” los parámetros en una propiedad input  (debe coincidir con el nombre del parámetro en el servicio).

$.ajax({
    url: "MyServiceSampe.svc/BuildFooFromType",
    type: "POST",
    data:  JSON.stringify({ "input":{ Name: "The name", Surname: "The surname" } }),              
    contentType: "application/json"
},
    function (response) {
        var foo = response;
        $("#foo_id").val(foo.Id);
        $("#foo_name").val(foo.Name);
        $("#foo_surname").val(foo.Surname);
});

Si analizamos el tráfico HTTP vemos la ejecución y respuesta del servicio en JSON.

image

Bueno, espero que este articulo os haya resultado interesante y haya aclarado algunas dudas sobre la forma de trabajar con WCF, AJAX y JSON.

Saludos y hasta la próxima. DJK

Pedro  Herrarte  Sánchez
Servicios WCF con AJAX y JSON.
Pedro Herrarte Sánchez

Pedro Herrarte, es consultor independiente, ofreciendo servicios de consultoría, análisis, desarrollo y formación. Posee mas de diez años de experiencia trabajando para las principales empresas de España. Es especialista en tecnologías .NET, entornos Web (ASP.NET, ASP.NET MVC,jQuery, HTML5), bases de datos (SQL Server y ORACLE) e integración de sistemas. Es experto en desarrollo (C#, VB.Net, T-SQL, PL/SQL, , ASP, CGI , C, Pro*C, Java, Essbase, Vignette, PowerBuilder y Visual Basic ...) y bases de datos (SQL Server y ORACLE). Pedro es MCP y MAP 2012, es fundador, diseñador y programador de www.devjoker.com..
Fecha de alta:03/05/2014
Última actualizacion:03/05/2014
Visitas totales:11074
Valorar el contenido:
Últimas consultas realizadas en los foros
Últimas preguntas sin contestar en los foros de devjoker.com