Aplicación Android invocando un Servicio Rest WCF Parte 1

jueves, 19 de enero de 2012

En este post voy a explicar un ejemplo sencillo de un servicio Rest WCF que devuelve la información en JSON y cómo puede ser invocado por una aplicación Android.

En esta primera parte veremos cómo crear el servicio.

El servicio que vamos a crear para el ejemplo es un servicio creado en .NET, utilizaremos la tecnología WCF, es la forma de crear servicios con .Net y además se puede conseguir interoperabilidad, que no es más que dos componentes programados en distintos lenjuages o tecnologías se puedan comunicar. En este ejemplo un servicio en C# es llamado por una aplicación Android en Java.


Para crear el servicio tenemos que crear un proyecto de tipo WCF Service Library
 en Visual Studio 2010.


Entre las referencias a ensamblados que agrega la plantilla de Microsoft para este tipo de proyecto se encuentra System.ServiceModel que es específica de WCF, para que nuestro servicio sea un servicio REST y sus métodos se ejecuten via URL es necesario añadir una referencia a System.ServiceModel.Web. Para poder añadir una referencia a este ensamblado el Target Framework del proyecto no debe ser .Net Framework 4 Client profile sino .Net Framework 4.
Una vez creado el proyecto, la plantilla de Microsoft crea dos ficheros, uno IService1 y otro Service1, los eliminamos y vamos a crear los siguientes.

Creamos un interface IService que será el contrato del servicio, contiene la definición de los métodos y/o funciones que va a tener el servicio; para indicar al motor de WCF que va a ser el contrato, tenemos que asignar el atributo ServiceContract al interface. Para indicar los métodos y/o funciones  que va a tener el servicio y por tanto van a ser visibles hay que indicar el atributo OperationContract. Para un servicio SOAP con esto podría ser suficiente para definir el contrato, pero como en nuestro ejemplo es un servicio REST que devuelve la información en JSON tenemos que añadir el atributo WebGet especificando el formato de respuesta en JSON.

[ServiceContract]
public interface IService
{
[OperationContract]

[WebGet(ResponseFormat = WebMessageFormat.Json)]
List<DTOCliente> GetClientes();


[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]

List<DTOProveedor> GetProveedores();
}

Como podemos apreciar en el código del Interface, vamos a utilizar objetos DTO (Data Transfer Object) para enviar la información solicitada al cliente, son objetos simples únicamente con propiedades y sin nada de lógica. Este tipo de objetos son una buena forma de enviar información entre aplicaciones o entre las capas de una aplicación, porque son ligeros y no estan acoplados a la implementación de la misma, de esta forma si en el futuro quisiéramos modificar por completo el servicio cambiando por ejemplo de ADO.net a EntityFramework en la capa de datos, el cliente no notaría el cambio porque sigue recibiendo el mismo tipo de objeto DTO, se puede decir que nuestro servicio será escalable.

[DataContract]
public class DTOCliente
{
[DataMember]
public string CodCliente { get; set; }
DataMember]
public string RazonSocial { get; set; }
[DataMember]
public string Direccion { get; set; }
[DataMember]
public string Telefono { get; set; }
}

[DataContract]
public class DTOProveedor
{
[DataMember]
public string CodProveedor { get; set; }
[DataMember]
public string RazonSocial { get; set; }
[DataMember]
public string Direccion { get; set; }
[DataMember]
public string Telefono { get; set; }
}

Creamos el servicio Service que es la implementación del Contrato. Cada función devuelve una lista genérica de DTOCliente o DTOProveedor.

public List<DTOCliente> GetClientes()

{      
List<DTOCliente> ListaClientes = new List<DTOCliente>();

ListaClientes.Add (new DTOCliente { CodCliente = "CLI0001", RazonSocial = "Cliente ejemplo 1", Direccion = "Avenida de America Nº 32 Madrid", Telefono = "915896369" }) ;

ListaClientes.Add (new DTOCliente { CodCliente = "CLI0002", RazonSocial = "Cliente ejemplo 2", Direccion = "Calle Jilgero Nº 24 Madrid", Telefono = "915896369" }) ;

ListaClientes.Add (new DTOCliente { CodCliente = "CLI0003", RazonSocial = "Cliente ejemplo 3", Direccion = "Calle Campomanes a Nº 45 Pozuelo de Alarcon", Telefono = "915896369" }) ;

ListaClientes.Add (new DTOCliente { CodCliente = "CLI0004", RazonSocial = "Cliente ejemplo 4", Direccion = "Calle Pinzón Nº 9 Madrid", Telefono = "915896369" }) ;

ListaClientes.Add (new DTOCliente { CodCliente = "CLI0005", RazonSocial = "Cliente ejemplo 5", Direccion = "Calle Nº 69 Madrid", Telefono = "915896369" }) ;

ListaClientes.Add (new DTOCliente { CodCliente = "CLI0006", RazonSocial = "Cliente ejemplo 6", Direccion = "Avenida de Abrantes Nº 25 Madrid", Telefono = "915896369" }) ;

ListaClientes.Add (new DTOCliente { CodCliente = "CLI0007", RazonSocial = "Cliente ejemplo 7", Direccion = "Avenida de de Nuestra señora de Fatima Nº 25 Madrid", Telefono = "915896369" });

return ListaClientes;

}public List<DTOProveedor> GetProveedores()

{List<DTOProveedor> ListaProveedores = new List<DTOProveedor>();

ListaProveedores.Add (new DTOProveedor{ CodProveedor = "PROV0001", RazonSocial = "Proveedor ejemplo 1", Direccion = "Calle Alcala Nº32 Madrid", Telefono = "915896369" }) ;

ListaProveedores.Add(new DTOProveedor { CodProveedor = "PROV0002", RazonSocial = "Proveedor ejemplo 2", Direccion = "Calle San Bernardo Nº45 Madrid", Telefono = "915896369" });

ListaProveedores.Add(new DTOProveedor { CodProveedor = "PROV0003", RazonSocial = "Proveedor ejemplo 3", Direccion = "Calle Princesa Nº14 Madrid", Telefono = "915896369" });

ListaProveedores.Add(new DTOProveedor { CodProveedor = "PROV0004", RazonSocial = "Proveedor ejemplo 4", Direccion = "Calle Goya Nº2 Madrid", Telefono = "915896369" });

ListaProveedores.Add(new DTOProveedor { CodProveedor = "PROV0005", RazonSocial = "Proveedor ejemplo 5", Direccion = "Calle Principe de Vergara Nº22 Madrid", Telefono = "915896369" });

ListaProveedores.Add(new DTOProveedor { CodProveedor = "PROV0006", RazonSocial = "Proveedor ejemplo 6", Direccion = "Calle Oca Nº5 Madrid", Telefono = "915896369" });

ListaProveedores.Add(new DTOProveedor { CodProveedor = "PROV0007", RazonSocial = "Proveedor ejemplo 7", Direccion = "Avenida de los Poblados Nº9 Madrid", Telefono = "915896369" });

return ListaProveedores;

}

}

Lo siguiente es el fichero config del servicio. Para poder devolver la información en JSON el endpoint debe ser webHttpBinding, con esto indicamos el protoloco a utilizar para comunicarse con el servicio.


<?xml version="1.0"?>

<configuration>

<system.web>

<compilation debug="true"/>

</system.web>

<system.serviceModel>

<services>

<service name="WCFServiceJSON.Service">

<endpoint address="" binding="webHttpBinding" contract="WCFServiceJSON.IService">

</endpoint>

</service>

</services>

<behaviors>

<serviceBehaviors>

<behavior>

<serviceMetadata httpGetEnabled="False"/>

<serviceDebug includeExceptionDetailInFaults="False"/>

</behavior>

</serviceBehaviors>

</behaviors>

</system.serviceModel>

<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>

</configuration>


Para terminar nuestro servicio WCF sólo nos queda hospedarlo. En este ejemplo vamos a hospedarlo en el servidor web Internet Information Service (IIS).
Para ello nos lo llevamos a la ruta donde se almacenan las aplicaciones web C:\inetpub\wwwroot y
creamos una carpeta nueva para nuestro servicio. En esta carpeta estará nuestro config en un fichero web.config y un fichero con extensión svc,  que define el servicio WCF, además creamos la carpeta bin donde alojamos la dll de nuestro servicio compilada.

Fichero Service.svc:

<%@ ServiceHost Language="C#" Debug="true" Service="WCFServiceJSON.Service" Factory=System.ServiceModel.Activation.WebServiceHostFactory%>

Factory=System.ServiceModel.Activation.WebServiceHostFactory esta instrucción es necesaria para que se puede ejecutar el servicio via URL.

Abrimos el Administrador de Internet Information Services y sobre el sitio web por defecto, agregamos una nueva aplicación




Es necesario que la aplicación de IIS tenga un grupo de aplicaciones enmarcado en Framework 4, debido a que es el framework en el que hemos desarrollado el servicio, si no dará error. Para hacer esto podemos crearnos un nuevo grupo de aplicaciones y enmarcarlo en Framework 4 o modificar uno existente.
.

Ya tenemos terminado nuestro servicio Rest con WCF y devolviendo los datos en JSON.

Para comprobar que funciona insertamos la URL, donde indicamos la operación a ejecutar, por ejemplo GetClientes



El texto del fichero devuelto por el servicio en formato JSON es el siguiente:

[{"CodCliente":"CLI0001","Direccion":"Avenida de America Nº 32 Madrid","RazonSocial":"Cliente ejemplo 1","Telefono":"915896369"},{"CodCliente":"CLI0002","Direccion":"Calle Jilgero Nº 24 Madrid","RazonSocial":"Cliente ejemplo 2","Telefono":"915896369"},{"CodCliente":"CLI0003","Direccion":"Calle Campomanes a Nº 45 Pozuelo de Alarcon","RazonSocial":"Cliente ejemplo 3","Telefono":"915896369"},{"CodCliente":"CLI0004","Direccion":"Calle Pinzón Nº 9 Madrid","RazonSocial":"Cliente ejemplo 4","Telefono":"915896369"},{"CodCliente":"CLI0005","Direccion":"Calle  Nº 69 Madrid","RazonSocial":"Cliente ejemplo 5","Telefono":"915896369"},{"CodCliente":"CLI0006","Direccion":"Avenida de Abrantes Nº 25 Madrid","RazonSocial":"Cliente ejemplo 6","Telefono":"915896369"},{"CodCliente":"CLI0007","Direccion":"Avenida de de Nuestra señora de Fatima Nº 25 Madrid","RazonSocial":"Cliente ejemplo 7","Telefono":"915896369"}]

En el próximo post veremos cómo invocar este servicio desde una aplicación Android.


Libros Relacionados



8 comentarios:

  1. Hola Jorge,

    Un gran ejemplo. Estoy deseando que publiques el de la parte Android, seguro que nos viene muy bien.

    Te quería comentar algo respecto al artículo. He visto que la parte servidora para generar el JSON pones algo como [WebGet(ResponseFormat = WebMessageFormat.Json)]

    De esta forma estas acoplando el formato del recurso REST directamente en el servidor. Que pasa si tuvieras que soportar varios formatos como XML y JSON? Como lo harías?

    Para utilizar toda la potencia de REST debería ser el cliente quien me diga el formato que quiere mediante la cabecera Accept, algo así como: Accept: application/json en este caso.

    Lo dicho, suerte con el blog, te seguiré con mucho interés :D

    ResponderEliminar
    Respuestas
    1. Hola Israel,

      Muchas gracias por el comentario.

      Tienes toda la razón, en este ejemplo sencillo que he planteado, el servicio solo devuelve la informacón en JSON.

      Como todo en este mundo hay varias formas de resolverlo para que pueda devolver en varios formatos y que sea el cliente el que lo decida.

      Me has dado una buena idea para un nuevo Post.

      Muchas gracias de nuevo.

      Eliminar
  2. no me funciona

    me sale el error siguiente:

    Error de servidor en la aplicación '/ServicioJSON'.

    No se puede cargar el archivo o ensamblado 'ServicioJSON' ni una de sus dependencias. Este ensamblado se creó con un tiempo de ejecución más reciente que el tiempo de ejecución cargado actualmente y no se puede cargar.

    a que se debe??

    ResponderEliminar
    Respuestas
    1. Hola

      Tiene pinta de que en el IIS tienes que cambiar el grupo de aplicaciones donde alojaste tu servicio al framework correspondiente de .net

      En el ejemplo yo le pongo framework 4.0.

      Eliminar
    2. Este comentario ha sido eliminado por el autor.

      Eliminar
    3. Si, ya me funciono, era eso, y bueno otro error que tenia en el app.connfig, pero de primera instancia era error de IIS (los grupos de configuracion)...te agradezco amigo, tengo un sitio web "ivansolutions.nixiweb.com" por si deseas publicar algo (Java, android o lo que sea)

      Eliminar
  3. Como agregaste al proyecto el archivo Service.svc?? yo estoy intentando agregarlo pero no me da la opcion.

    ResponderEliminar
    Respuestas
    1. Hola Edel

      Al crear el proyecto como Wcf Service Library, este puede ser hospedado no solo en IIS sino en cualquier otro proceso como un exe o servicio de windows, es por esto que no se añade por defecto este fichero.

      Como en este ejemplo finalmente se hospeda en IIS lo que hice fue crearme el fichero manualmente y luego añadirlo al proyecto mediante la opcion Add/ Existing Item desde las opciones que salen con botón derecho sobre el proyecto.

      saludos

      Eliminar