jueves, 12 de diciembre de 2013

Dispositivos móviles ANDROID consumiendo .NET WCF REST

En esta ocasión y continuando con el mundo Java, veamos como nuestros actuales servicios WCF de .NET pueden ser expuestos como REST (Representational State Transfer) además de permanecer dando funcionalidad SOAP como hasta ahora. 
Actualmente ya existen numerosos artículos que hablan al respecto así que nos centraremos concretamente en las adaptaciones de nuestros servicios WCF .NET y la invocación correcta desde el Emulador de Android y Eclipse.
Cada vez más los dispositivos móviles son parte de cada minuto en nuestra vida. Toda compañía quiere acercar más su negocio a cada individuo e involucrarse en esta nueva era. REST tiene la particularidad adicional de poder ser consumido fácilmente por cualquiera de ellos de manera estándar minimizando impactos en el ancho de banda. Además, HTML 5 también está adquiriendo gran importancia y gracias a estos servicios REST, JQuery aporta la comunicación más adecuada con nuestros servicios.
Web API, es la recomendación de Microsoft al la creación de servicios REST desde cero. No obstante, si queremos dar a nuestros clientes la oportunidad de no tener que realizar una gran inversión en la creación de nuevos servicios veamos cuales serían nuestros pasos:
Creando Servicio WCF REST .NET
1) Creamos nuestro servicio WCF desde Visual Studio .NET, a partir de un proyecto de tipo “WCF Service Application” e indicamos como nombre “WcfService1”:
image
2) Modificamos el Service Contract para incluir las siguientes instrucción como puede verse a continuación:
[ServiceContract]public interface IService1{
    [OperationContract]
    [WebGet(
        UriTemplate = "GetData/{value}",
        BodyStyle = WebMessageBodyStyle.WrappedRequest,
        ResponseFormat = WebMessageFormat.Json,
        RequestFormat = WebMessageFormat.Json)]    string GetData(string value);

    [OperationContract]
    [WebInvoke(
        Method = "POST",
        UriTemplate = "GetDataUsingDataContract",
        BodyStyle = WebMessageBodyStyle.Bare, /* Importante. Usar "Bare" */
        ResponseFormat = WebMessageFormat.Json,
        RequestFormat = WebMessageFormat.Json)]
    CompositeType GetDataUsingDataContract(CompositeType composite);
}

3) Ejecutamos el servicio a fin de comprobar que todo esta correcto. “Aunque este mensaje puede indicarnos que se trata de un error, no es así”.

image

Instalando el plug-in de Android en Eclipse

4) En Eclipse, desde el menú: “Help – Install New Software…” e indicamos “https://dl-ssl.google.com/android/eclipse/” en el campo “Work with”:

imageimage

5) Accedemos a la carpeta “C:\Users\<USUARIO>\android-sdks” donde encontraremos el SDK de Android instalado.

6) Ejecutamos  “SDK Manager.exe”, marcamos “Android 4.2 (API 17)” e instalamos los 7 paquetes. (“En mi caso, como muestra la figura, se encuentran instados”):

image

7) Una vez instalado,  configuramos cualquiera de los emuladores de Android, por ejemplo, el de “Nexus One”:

Ejecutamos “AVD Manager.exe” (Android Virtual Device)

imageimage

8 Acceso al servicio desde .NET 4.0

8.1) Para la serialización/deserialización JSON optaremos por “Newtonsoft.Json.dll” (http://james.newtonking.com/pages/json-net.aspx).

8.2) A continuación completamos el código de nuestras peticiones GET y POST con el siguiente código:

Petición GET


   1: string strDataRest = String.Empty;
   2:  
   3: WebRequest request = WebRequest.Create(REST_URL_GET);
   4: using (WebResponse ws = request.GetResponse())
   5: {
   6:     using (StreamReader sr = new StreamReader(ws.GetResponseStream()))
   7:     {
   8:         string strJson = sr.ReadToEnd();
   9:         strDataRest = JsonConvert.DeserializeObject<string>(strJson);
  10:     }
  11: }

Petición POST


   1: CompositeType newCompositeData = new CompositeType() { BoolValue = true, StringValue = "ABC" };
   2: CompositeType compositeDataRest = null;
   3:  
   4: string jsonString = JsonConvert.SerializeObject(newCompositeData);
   5: byte[] requestBytes = ASCIIEncoding.UTF8.GetBytes(jsonString);
   6:                
   7: HttpWebRequest reqPost = WebRequest.Create(REST_URL_POST) as HttpWebRequest;
   8: reqPost.Method = "POST";
   9: reqPost.Accept = "application/json";
  10: reqPost.ContentType = "application/json";
  11: reqPost.ContentLength = requestBytes.Length;
  12: reqPost.Headers.Add("json", jsonString);
  13:                 
  14:  
  15: using (Stream postStream = reqPost.GetRequestStream())
  16: {
  17:     postStream.Write(requestBytes, 0, requestBytes.Length);
  18: }
  19:  
  20: using (HttpWebResponse response = reqPost.GetResponse() as HttpWebResponse)
  21: {
  22:     if (response.StatusCode != HttpStatusCode.OK)
  23:         throw new Exception(String.Format(
  24:             "Server error (HTTP {0}: {1}).",
  25:             response.StatusCode,
  26:             response.StatusDescription));
  27:  
  28:     using (StreamReader sr = new StreamReader(response.GetResponseStream()))
  29:     {
  30:         string strJson = sr.ReadToEnd();
  31:         compositeDataRest = JsonConvert.DeserializeObject<CompositeType>(strJson);
  32:     }
  33: }


By Edner LLacsa

martes, 10 de diciembre de 2013

Consumir Servicios Web WCF con KSOAP2 - Android

A continuación detallo, como consumir servicios web con Android. KSOAP2, REST, y otros modos alternativos e igualmente útiles serán tratados. El mejor a vuestra elección, según la carga de la API, el dispositivo, ancho de banda disponible, etc..

De entre los más usuados en la mayoría de los casos se encuentra la librería independiente KSOAP2 creada para J2ME.. (aún me acuerdo de los cursos de master que prepare utilizando esto..) .

KSOAP2 es una librería ligera y eficiente, características imprescindibles para su utilización en entornos de aplicaciones móviles.  Desde la página del proyecto hospedado en Google Code podemos bajarnos la última versión de la librería para incluir en nuestro proyecto de Eclipse.

Pasos iniciales a seguir:

1- Bajar la última versión del jar (a fecha 7/04/2011) - http://code.google.com/p/ksoap2-android/source/browse/m2-repo/com/google/code/ksoap2-android/ksoap2-android-assembly/2.5.4/ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar
2- Crear un proyecto de Android.
3- Incluir la librería en el proyecto de Eclipse.



Bueno... ya estamos listos para utilizarla. Lo primero, vamos a explicar los conceptos fundamentales.

Necesitamos datos sobre el ENDPOINT, es decir:
1- Dirección url del servicio web.
2- Namespace
3- Método a ejecutar del servicio web.
4- Derivado --> La acción SOAP a ejecutar.

Ejemplo:

1
2
3
4
private static final String url = "http://www.webservicex.net/geoipservice.asmx"; 
private static final String namespace = "http://www.webservicex.net/"; 
private static final String Metodo_GetGeoIP = "GetGeoIP"; 
private static final String accionSoap_GetGeoIP = "http://www.webservicex.net/GetGeoIP"; 
Una vez identificados los datos que necesitamos, podemos proceder a construir la solicitud al método del servicio.
  1. Primero hemos de identificar los parámetros y el tipo de datos devuelto por el método del servicio.
  2. Una vez identificados, se procede a construir la petición SOAP utilizando la clase SoapObject.
  3. Seguidamente se construye el "sobre" del mensaje SOAP: En la parametrización, se especifica el tipo de protocolo de comunicación (SOAP1.1 / 1.2, etc..) y como característica especial si el EndPoint es un servicio dotNet
  4. A la petición (objeto request) se la añaden los parámetros con el método AddProperty.
  5. Se construye el objeto de transporte para invocar el método (clase HttpTransportSE).
  6. Al invocar al método "call" de la clase "HttpTransportSE" se recogen los resultados del servicio.
  7. Finalmente se recogen los resultados utilizando el objeto devuelto (response) e invocando al método getProperty.

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
2021
22
23
24
2526
27
28
29
3031
32
33
34
3536
37
38
39
4041
public class ResultadoGeoIPService {
        private String NombrePais; 
        private String CodigoPais;
        public String getNombrePais() {
                return NombrePais;        }
        public void setNombrePais(String nombrePais) {
                NombrePais = nombrePais;
        }
        public String getCodigoPais() {                return CodigoPais;
        }
        public void setCodigoPais(String codigoPais) {
                CodigoPais = codigoPais;
        }}
 
 
 //... EN LA CLASE PROXY DEL SERVICIO ...
        public ResultadoGeoIPService GetGeoIP(String IP) throws Exception{                try {   
                   SoapObject request = new SoapObject(namespace, Metodo_GetGeoIP);
                   SoapSerializationEnvelope sobre = new SoapSerializationEnvelope(SoapEnvelope.VER11);
                   sobre.dotNet = true;
                   request.addProperty("IPAddress", IP);                   sobre.setOutputSoapObject(request);
                   
                   HttpTransportSE transporte = new HttpTransportSE(url);
                   transporte.call(accionSoap_GetGeoIP, sobre);
                   SoapObject resultado = (SoapObject) sobre.getResponse();        
                   ResultadoGeoIPService res=new ResultadoGeoIPService();
                   
                   res.setNombrePais(resultado.getProperty("CountryName").toString());
                   res.setCodigoPais(resultado.getProperty("CountryCode").toString());                   return res;
                
                }catch (Exception e){
                         throw(e);
                }         }
A continuación dejo un ejemplo de código completo en un proyecto de Eclipse. En este ejemplo encontrareís:
  • La clase "ProxyGeoIPService" que utiliza un servicio web que averigua el país de una dirección IP. También posee otro método (GetGeoIPContext) que en función de la dirección IP origen de la petición recibida devuelve el país al que corresponde la solicitud.
  • Una clase "InetManager" que permite obtener la dirección IP del dispositivo Android.

El código que dispará la invocación al servicio web lo podeís encontrar en el evento OnClick (OnClickbtnLlamarGeoIPService) del Botón de la interfaz de la actividad principal.
1
2
3
4
56
7
8
9
1011
12
13
14
1516
    private OnClickListener OnClickbtnLlamarGeoIPService = new OnClickListener() {
                public void onClick(View v) {
                        ProxyGeoIPService srvGeoIP=new ProxyGeoIPService();
                        String IP=InetManager.getLocalIpAddress();
                        lblIP.setText(IP);                        try {
                                //ResultadoGeoIPService res=srvGeoIP.GetGeoIP(IP);
                                ResultadoGeoIPService res=srvGeoIP.GetGeoIPContext();
                                lblResultado.setText(res.getNombrePais());
                        } catch (Exception e) {                                // TODO Auto-generated catch block
                                Log.e(Config.LOGKSOAP,e.toString());
                        }
 
                }            };



By. Edner Llacsa
 http://ednerllacsa.blogspot.com/

sábado, 7 de diciembre de 2013

Desarrollando Aplicaciones WCF para Android

¿Cómo utilizar el servicio WCF con Android?


Estoy creando un servidor en .net y una aplicación cliente para Android. Me gustaría implementar un método de autenticación que envía el nombre de usuario y contraseña para el servidor y un servidor envía una cadena de sesión.
No estoy familiarizado con WCF para que realmente les agradecería su ayuda.
En java he escrito el siguiente método:
private void Login()
{
  HttpClient httpClient = new DefaultHttpClient();
  try
  {
      String url = "http://192.168.1.5:8000/Login?username=test&password=test";

    HttpGet method = new HttpGet( new URI(url) );
    HttpResponse response = httpClient.execute(method);
    if ( response != null )
    {
      Log.i( "login", "received " + getResponse(response.getEntity()) );
    }
    else
    {
      Log.i( "login", "got a null response" );
    }
  } catch (IOException e) {
    Log.e( "error", e.getMessage() );
  } catch (URISyntaxException e) {
    Log.e( "error", e.getMessage() );
  }
}

private String getResponse( HttpEntity entity )
{
  String response = "";

  try
  {
    int length = ( int ) entity.getContentLength();
    StringBuffer sb = new StringBuffer( length );
    InputStreamReader isr = new InputStreamReader( entity.getContent(), "UTF-8" );
    char buff[] = new char[length];
    int cnt;
    while ( ( cnt = isr.read( buff, 0, length - 1 ) ) > 0 )
    {
      sb.append( buff, 0, cnt );
    }

      response = sb.toString();
      isr.close();
  } catch ( IOException ioe ) {
    ioe.printStackTrace();
  }

  return response;
}
By: Edner Llacsa
http://ednerllacsa.blogspot.com/


sábado, 30 de noviembre de 2013

CRUD BÁSICO CON WCF

CRUD BÁSICO CON WCF DATA SERVICES


En este artículo vamos a ver cómo usar WCF Data Services para interactuar con nuestra base de datos mediante REST, para esto vamos a realizar un formulario de CRUD básico y seguiremos los siguientes pasos:

1.       Crear aplicación Asp.net
2.       Crear modelo de datos con Entity Framework
3.       Crear WCF Data Service
4.       Configurar WCF Data Service para acceso a nuestras entidades.
5.       Interactuar  con nuestro servicio desde una aplicación asp.net

¿Qué es WCF Data Services?
También conocido como ADO.NET data services, es un componente del .net Framework que permite crear servicios web usando ODATA (Open Data Protocol), para exponer y consumir datos en la web mediante REST, ODATA expone los datos como recursos que son accesibles y modificados a través de URIs, usando los verbos HTTP GET(Consultar), PUT(Modificar), POST(Ingresar) y DELETE(Eliminar).

Creando nuestro modelo de datos con la DB ejemplo Northwind.
Antes que nada para crear el modelo debemos tener la base de datos Northwind en nuestra instancia de SQl Server, dichas base de datos se adjunta en este artículo para que se sea descargada y restaurada. Una vez tengamos esta DB, en nuestro proyecto web hacemos click derecho, agregar un nuevo elemento y seleccionamos, ADO:NET Entity Data Model.




Luego configuramos la conexión con la base de datos:



Y seleccionamos las tablas que necesitemos de nuestra base de datos.



Creando nuestro WCF Data Service.
Ahora que tenemos creado nuestro modelos de datos, procedemos a crear nuestro servicio de datos, para esto hacemos clic derecho, agregar nuevo elemento, y elegimos Servicio de datos WCF.



Enseguida nos crea nuestro Data service, y nos indica que debemos especificar el origen de datos y configurar los permisos para las entidades que vamos a exponer en el servicio.

public class WcfDataService1 : DataService/* TODO: escriba aquí el nombre de clase del origen de datos */ >
{
// Se llama a este método una única vez para inicializar directivas aplicables a todo el ámbito del servicio.
        public static void InitializeService(DataServiceConfiguration config)
        {
// TODO: establezca reglas para indicar qué operaciones de servicio y conjuntos de entidades son visibles, actualizables, etc.
            // Ejemplos:
// config.SetEntitySetAccessRule("MiConjuntoDeEntidades", EntitySetRights.AllRead);
// config.SetServiceOperationAccessRule("MiOperaciónDeServicio", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }
}



En nuestro caso el origen de datos es NorthwindEntities que hace referencia al modelo que creamos con entity Framework, y vamos a especificar permisos de crear, leer, actualizar y eliminar datos en la tabla Customers de nuestra DB, la configuración del servicio nos queda así:

public class NorttwindAccess : DataService<NorthwindEntities>
{
// Se llama a este método una única vez para inicializar directivas aplicables a todo el ámbito del servicio.
        public static void InitializeService(DataServiceConfiguration config)
        {
// TODO: establezca reglas para indicar qué operaciones de servicio y conjuntos de entidades son visibles, actualizables, etc.
            // Ejemplos:
// config.SetEntitySetAccessRule("MiConjuntoDeEntidades", EntitySetRights.AllRead);
// config.SetServiceOperationAccessRule("MiOperaciónDeServicio", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;

            config.SetEntitySetAccessRule("Customers"EntitySetRights.All);
            config.UseVerboseErrors = true;
        }
}

Cabe resaltar la configuración de UseVerboseErrors en True, esto para lograr obtener el detalle completo de la excepción desde el web services, en caso de que ocurra algún error.

Ahora tenemos configurado nuestro servicio de datos, lo podemos probar ingresando a la URL http://localhost:1995/NorttwindAccess.svc donde NorttwindAccess es el nombre de nuestro servicio.

  

Nos muestra las tablas a la cuales otorgamos permisos, en este caso solo la tabla Customeres.
También podemos hacer cualquier query a través de la URI de nuestro servicio, algunos ejemplos a continuación:

·         Seleccionar todos los registros de la tabla Customers:

·         Seleccionar los registros donde el Campo CustomerID sea igual a “ALFKI”:
·         Seleccionar todos los registros de la tabla Customers ordenados por el campo ContactNAme:

·         Seleccionar todos los registros de la tabla Customers donde el campo ContactName termine en “no”:
http://localhost:1995/NorttwindAccess.svc/Customers?$filter=endswith(ContactName, 'no')

·         Seleccionar los campos CustomerID y ContactName de la tabla Customers:

Estos son algunos ejemplos de los tantos que se pueden hacer.


Ahora procedemos a referenciar nuestro nuevo servicio de datos a nuestra aplicación web asp.net, para poder interactuar con él.



Una vez tenemos nuestro servicio de datos referenciado podemos interactuar con el desde nuestra aplicación.

En nuestro ejemplo vamos a crear un CRUD básico para la tabla Customers, visualmente es de la siguiente forma:




Para poblar el GridView con todos los Clientes, creamos el siguiente método el cual será invocado en el evento Load de nuestra página.


private void LlenarGrid()
{
var serv = new NorthwindService.NorthwindEntities(newUri("http://localhost:1995/NorttwindAccess.svc"));

       var clientes = (from c in serv.Customers
                       orderby c.ContactName
                       select c).ToList();

       this.gvCustomers.DataSource = clientes;
       this.gvCustomers.DataBind();
}


Observemos que inicializamos nuestro modelo de datos a partir de nuestro servicios de datos, y sobre el podemos ejecutar cualquier consulta linq to entities, en este caso obtenemos  todos los registros de la tabla Customers y cargamos el GridView con los resultados.


Ahora para eliminar un registro de la tabla Customers, en el vento gvCustomers_RowDeleting
De nuestro gridView asignamos el siguiente fragmento de código:


try
{
string strID = this.gvCustomers.Rows[e.RowIndex].Cells[0].Text;
var serv = new NorthwindService.NorthwindEntities(newUri("http://localhost:1995/NorttwindAccess.svc"));
       NorthwindService.Customers eliminarCliente = (from c in serv.Customers
                                                    where c.CustomerID.Equals(strID)
                                               select c).Single();
       serv.DeleteObject(eliminarCliente);
       serv.SaveChanges();
       this.lblError.Text = "El cliente se elimino correctamente.";
       this.LlenarGrid();
}
catch (Exception ex)
{
this.lblError.Text = string.Format("Ocurrió un error al eliminar el cliete: {0}", ex.Message);
}



Para terminar con nuestro ejemplo, vamos a observar el código alojado en el evento click del botón guardar, en el cual se ejecutan las inserciones y actualizaciones a nuestra DB:

try
{
var serv = new NorthwindService.NorthwindEntities(newUri("http://localhost:1995/NorttwindAccess.svc"));

       if (this.hfAccion.Value.Equals("Nuevo"))
       {
NorthwindService.Customers customer = new NorthwindService.Customers
             {
                    CustomerID = this.txtID.Text,
                    ContactName = this.txtNombre.Text,
                    CompanyName = this.txtCompania.Text
             };
             serv.AddToCustomers(customer);
       }
       else
       {
                               NorthwindService.Customers modificarCustomer =

(from c in serv.Customers
              where c.CustomerID.Equals(this.txtID.Text)
              select c).Single();
              modificarCustomer.ContactName = this.txtNombre.Text;
              modificarCustomer.CompanyName = this.txtCompania.Text;
              serv.UpdateObject(modificarCustomer);
       }

       serv.SaveChanges();
       this.lblError.Text = "El cliente se actualizó correctamente.";
       this.hfAccion.Value = "Nuevo";
       this.txtID.Enabled = true;
       this.LlenarGrid();
}
catch (Exception ex)
{
this.lblError.Text = string.Format("Ocurrió un error al ingresar el cliete: {0}", ex.Message);
}

Con esto doy por terminado el artículo, espero que sea de gran utilidad para muchos, adicional el link de los fuentes de la solución y el .bak de la base de datos a continuación. En un próximo artículo estaré mostrando como consumir estos Data Services  mediante Jquery a través de una petición AJAX.

Saludos,
Edner LLacsa
http://ednerllacsa.blogspot.com/