WCF bajo Contrato (2/4)


Contrato de Datos

WCF emplea, de forma predeterminada, a la clase DataContractSerializer como mecanismo de serialización de datos .NET desde y hacia XML, el cual requiere que los tipos tengan un contrato de datos definido.

Hasta ahora el servicio utiliza tipos simples (string) para el intercambio de datos (en el parámetro de entrada y el valor devuelto) sin ninguna preparación. Esto se debe a que ciertos tipos del .NET Framework, entre ellos los “primitivos”, tienen contratos de datos predeterminados. Si lo desea puede consultar la lista de los tipos admitidos por el DataContractSerializer.

En caso que deseáramos utilizar nuestros propios tipos de datos, necesitamos definir tipos complejos. Para ello debemos crear tipos que tengan un contrato de datos definido, lo cual conseguimos aplicando el atributo DataContract a las clases, estructuras y/o enumeraciones a ser serializables por el DataContractSerializer. Además de lo anterior debemos aplicar el atributo DataMember a los miembros que deseemos sean serializables, sin que importe su modificador de acceso.

Continuando con nuestro ejemplo, supongamos que ahora deseamos utilizar los siguientes tipos para el intercambio de datos:

Listado de HelloData.cs

using System;
using System.Runtime.Serialization;

namespace hello.data
{
    [DataContract(Namespace="http://hello/data/")]
    public class Person
    {
        private string firstName;
        private string lastName;

        [DataMember()]
        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }

        [DataMember()]
        public string LastName
        {
            get { return lastName; }
            set { lastName = value; }
        }
    }

    [DataContract(Namespace="http://hello/data/")]
    public class HelloCard
    {
        private string greeting;
        private int serial;

        [DataMember()]
        public string Greeting
        {
            get { return greeting; }
            set { greeting = value; }
        }

        public int Serial
        {
            get { return serial; }
            set { serial = value; }
        }
    }
}

Nótese que son clases “planas” con los atributos que definen el contrato de datos. Observe también la declaración del espacio de nombre del .NET Framework: System.Runtime.Serialization, a cuyo ensamblado debemos referenciar para compilar HelloData.cs:

>csc /t:library HelloData.cs /r:System.Runtime.Serialization.dll

Una vez definidos los tipos personalizados, ahora definimos el nuevo contrato de servicio, y reescribimos su implementación, como se lista a continuación:

Listado de Hello.cs

using System;
using System.Text;
using System.ServiceModel;
using hello.data;

namespace hello
{
  [ServiceContract(Namespace="http://hello/" Name="Hello")]
  interface IHello
  {
    [OperationContract()]
    public HelloCard SayHello(Person person);
  }

  [ServiceBehavior(Namespace="http://hello/", Name="HelloService")] 
  public class Hello : IHello
  {
    private StringBuilder message = new StringBuilder("¡Hola ");
  
    public HelloCard SayHello(Person person)
    {      
      if (person == null ||
          person.FirstName == null ||
          person.FirstName.Length == 0)
        throw new FaultException("Objeto Person inválido.");

      message.Append(person.FirstName + "!");
      string msg = message.ToString();
      HelloCard card = new HelloCard();
      card.Greeting = msg;
      System.Console.WriteLine(msg);
      return card;
    }
  }
}

Nota: En el código se altera la interfaz del contrato del servicio, cuando en la práctica se debe definir una nueva interfaz e implementarla. Se hizo así para simplicidad del ejemplo.

Ahora compilamos el servicio agregando la referencia al ensamblado generado previamente:

>csc /t:library Hello.cs /r:System.ServiceModel.dll,HelloData.dll

El host y su archivo de configuración permanecen sin cambios, por lo que solo resta ejecutar HelloHost.exe.

Ahora pasamos al cliente. Primero regeneramos los artefactos cliente con svcutil.exe como hasta ahora, y después modificamos el código de la aplicación cliente, tal como se aprecia a continuación:

Listado de Client.cs

using System;

public class Client
{
  static void Main(string[] args)
  {
    String arg = null;
    String result = null;
    if (args.Length > 0) {
      arg = args[0];
    }
    else {
      arg = "Anónimo";
    }
    try {
      hello.Hello service = new hello.HelloClient();
      hello.data.Person person = new hello.data.Person();
      person.FirstName = arg;
      hello.data.HelloCard card = service.SayHello(person);
      result = card.Greeting;
    }
    catch (System.ServiceModel.FaultException fault) 
    { 
      result = "Fault: " + fault.Message; 
    }
    catch (Exception ex) {
      result = ex.ToString();
    }
    finally{
      System.Console.WriteLine(result);
    }
  }
}

Compilamos los archivos del proxy y el cliente, y ejecutamos Client.exe como hasta ahora.

Nota: Además de DataContractSerializer, WCF también admite (de forma excluyente) la clase XmlSerializer, que es el mismo mecanismo de serialización utilizado en Servicios Web ASP.NET (aka ASMX). Aunque XmlSerializer solo admite un conjunto reducido de tipos, permite un mayor control sobre el XML resultante y admite mejor la norma de XSD. Para más información consulte Utilización de XMLSerializer.

Acerca de Willy Mejia

Developer, Techie, Human... http://about.me/willyxoft
Esta entrada fue publicada en .NET, NetFx3, WCF. Guarda el enlace permanente.

2 respuestas a WCF bajo Contrato (2/4)

  1. Tania dijo:

    Que onda!!!

    Buen blog. Se lo he recomendado a algunos amigos.

    Estoy invitando a varios bloggers que me laten a visitar el blog que estamos haciendo en Prodigy/MSN:
    http://elblogprodigymsn.spaces.live.com

    Ahí te lo dejo para que lo veas

    Saludos

    Tania

  2. Pingback: WCF bajo Contrato (3/4) « WillyXoft

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s