XFire y Eclipse

Febrero 16, 2010 :: Posted by - Emilio Torrens :: Category - , ,

XFire te permite generar el código necesario para un cliente de webservice a partir de su WSDL

image  Para usarlo con Eclipse debes instalar el Plugin, para eso vas al menú Help/Install New Software le das a Add en Name le pones XFire y en location le pones esta dirección “http://dist.codehaus.org/xfire/update/”, Ok, Finish y ya lo tienes instalado.

image  Para usarlo vas al proyecto, New/Other, buscas el Wizard de XFire y allí solo tienes que poner la dirección del WSDL y donde quieres que te genere el código y listo.

Con estos pocos pasos ya tienes todas las clases necesarias para acatar el servicio, además con XFire no he tenido problemas con los WSDL de ningún servicio.

Es importante que añadas commons-httpclient-3.0.jar y commons-codec.jar al proyecto ya que XFire las necesita.

SoapHeader, SoapExtensions y Herencia

Diciembre 03, 2009 :: Posted by - Emilio Torrens :: Category - , , ,

Hace unos días Jordi escribió sobre las SoapExtensions y yo sobre las SoapHeaders, hoy le añadimos herencia y vemos como ahorrarnos bastante código y trabajo en una capa de servicios. :)

La idea es que todos los métodos de todos los servicios web de la aplicación se autentifiquen en el mismo sitio y no tener que poner el código de autentificación en cada método, además no queremos usar cookies ni mantenimiento de sesión.

Para esto usaremos una Cabecera Soap donde el cliente nos enviara Usuario y Contraseña, debemos crear la clase cabecera:

public class SoapHeaderCredentials : SoapHeader
{
    public string Password = "";
    public string UserName = "";
}

Cada servicio web tiene que tener una propiedad con la Cabecera, para ahorrarnos el escribirlo cada vez, creamos una clase que herede de WebService, que contenga la propiedad y heredamos los servicios web de esa clase:

public class MyWebService : System.Web.Services.WebService
{
    public SoapHeaderCredentials soapHeaderCredentials;
}

public class Service : MyWebService

Después creamos una Extensión Soap de autentificación (en este caso la llamamos AuthenticationExtension), Jordi ya explica aquí como crearlas así que solo pongo el código que nos interesa, que es donde buscamos la Cabecera Soap en el Método ProcessMessage:

case SoapMessageStage.AfterDeserialize:
{
    var o = from h in message.Headers.Cast<SoapHeader>()
            where h.GetType() == typeof(SoapHeaderCredentials)
            select h ;
    SoapHeaderCredentials soapHeaderCredentials =
        (SoapHeaderCredentials) o.First();
    AuthenticateUser(
        new Credentials()
        {
          UserName = soapHeaderCredentials.UserName,
          Password = soapHeaderCredentials.Password,
        }, 
      );
    break;
}

Después solo queda añadir los dos atributos [SoapHeader("soapHeaderCredentials")]  y [AuthenticationExtension()] a nuestros WebMethods, eso hará que los métodos tengan la cabecera de usuario y contraseña y que ejecuten el código de autentificación al recibir un mensaje:

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

Y listo :)

Cabeceras en mensajes SOAP

Noviembre 27, 2009 :: Posted by - Emilio Torrens :: Category - , ,

Añadir cabeceras personalizadas a los mensajes de nuestros servicios web es realmente sencillo, en esas cabeceras podemos transportar cualquier dato que nos interese tokens, usuario y contraseña, lo que sea..

Hay que hacer lo siguiente:

1- Crear la clase con los datos que herede de SoapHeader

public class SoapHeaderData: SoapHeader
{
    public string Data1;
    public string Data2;
    public string Data3;
}

2- Crear una propiedad en el servicio web con esa clase y la etiqueta SoapHeader con el nombre de la propiedad al método web, en esa propiedad tendremos los datos

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
    public SoapHeaderData HeaderData;

    [WebMethod]
    [SoapHeader("HeaderData")]
    public string HelloWorld() {
        return "Hello World " + HeaderData.Data1 + ", " +
                                HeaderData.Data2 + ", " +
                                HeaderData.Data3;
    }
}

Solo haciendo esto ya tenemos la cabecera en nuestra petición SOAP:

image

Generando clases en Java desde WSDL autogenerados (asmx)

Abril 14, 2009 :: Posted by - Emilio Torrens :: Category - ,

Tenemos un par de Clientes que usan Java y tienen que consumir los servicios web de nuestras aplicaciones (asmx), hemos tenido muchos problemas generando las clases desde Eclipse o el Intellij IDEA desde el wsdl autogenerado de los asmx.

Al final hemos encontrado la solución, usar el XFIRE, usando ese framework de Java no hemos tenido problemas

Aquí hay un quickstart de cómo utilizar el plugin en el Eclipse:

http://xfire.codehaus.org/Eclipse+Plugin

Documentación:

http://xfire.codehaus.org/User’s+Guide

Hay una nueva versión que se llama CXF

http://cxf.apache.org/

Aunque no la hemos probado, así que para ir sobre seguro usa o recomienda usar XFIRE

Pasar Credenciales en Http Header Authorization

Noviembre 27, 2008 :: Posted by - Emilio Torrens :: Category - , ,

Me he estado volviendo medio loco estos días intentando conectar con el servicio de un tercero, la documentación no era todo lo clara que uno espera…

Intente pasarle las Credenciales como NetworkCredentials en el HttpRequest y nada, añadiendo cabeceras de autentificación al mensaje SOAP y nada, al final las espera en una cabecera Http.

¿Como se pasan allí? pues así:

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("la url del servicio");

req.Headers.Add("SOAPAction", "la accion");
req.ContentType = "application/soap+xml";
req.Accept = "text/xml";
req.Method = "POST";
byte[] authBytes = Encoding.UTF8.GetBytes(("Usuario:Pass").ToCharArray());
req.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(authBytes));       

Cliente SOAP para servicios PHP o Java AXIS

Abril 14, 2008 :: Posted by - Emilio Torrens :: Category - , , ,

Aquí dejo una clase para consumir servicios web vía SOAP en los que no tengamos el WSDL o que el Wizard nos de problemas:

using System;
using System.Text;
using System.IO;
using System.Net;
using System.Xml;

namespace Test
    {
    class SOAPClient
        {

        public static XmlDocument SendMsg(XmlDocument xmlRQ)
            {
                byte[] byte1;
                Stream myStream;
                StreamReader readStream;

                HttpWebRequest wr =
                    (HttpWebRequest)WebRequest.
                    Create("http://laurl.com/ws.php");

                byte1 =
                Encoding.GetEncoding(1252).GetBytes(xmlRQ.OuterXml);
                wr.Method = "POST";
                wr.Headers.Add("SOAPAction", "");
                wr.ContentType = "text/xml; charset=\"utf-8\"";
                wr.Accept = "text/xml";

                myStream = wr.GetRequestStream();
                myStream.Write(byte1, 0, byte1.Length);
                myStream.Close();

                myStream = wr.GetResponse().GetResponseStream();
                readStream = new StreamReader(myStream);
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(readStream);
                myStream.Close();

                return getSOAPPayload(xmlDoc, "body");
            }

          private static XmlDocument getSOAPPayload(XmlDocument rs,
                                                    string Tag)
            {

                XmlNode xmlNode =
                    rs.GetElementsByTagName(Tag)[0].FirstChild;
                XmlDocument xmlResult = new XmlDocument();
                xmlResult.LoadXml(xmlNode.Value);
                return xmlResult;
            }

        }
    }

ASP.NET Servicios Web y CacheDuration (de paso como activar POST y GET en nuestros servicios web)

Noviembre 08, 2007 :: Posted by - Emilio Torrens :: Category - ,

CacheDuration es un atributo de WebMethod con el que podemos implementar de manera muy sencilla un sistema de chache basado en el tiempo, cuando le indicamos la duración del Cache (en segundos) el servidor guarda los parámetros del request y la respuesta, así mientras no caduque el cache para parámetros iguales el código de nuestro método no se ejecutara y devolverá el resultado desde el cache.

Podéis probar con este código, la primera vez tardara 5 segundos, pero durante el siguiente minuto, para el mismo Texto, será instantáneo:

WebMethod(CacheDuration=60)]
 public int CountChars(string Text)
 {
     System.Threading.Thread.Sleep(5000);
     return String.IsNullOrEmpty(Text) ? 0 : Text.Length;
 }

Ojo que las peticiones vía POST no se guardan en el cache y la pagina de pruebas de los servicios web funciona con POST, así que debes probarlo o bien por SOAP o bien por GET.

Por defecto los servicios web llevan el GET y el POST desactivado, para activarlos solo tenéis que añadir esto dentro de <system.web> en el Web.config:

<webServices>
   <protocols>
      <add name="HttpGet"/>
      <add name="HttpPost"/>
   </protocols>
</webServices>