jueves, 1 de agosto de 2013

Ejemplo Sencillo de Windows Communication Foundation (WCF)


Windows Communication Foundation (WCF) de Microsoft es una nueva tecnología para la creación de sistemas distribuidos y de desarrollo de aplicaciones basadas en arquitecturas orientadas a servicios (SOA), mediante Visual Studio 2010 o 2008 e inclusive en 2005. Esta se puede ejecutar en una máquina local, en una Lan o en Internet de forma segura. Mediante los sistemas de arquitectura orientada a servicios se facilita la interacción entre diferentes sistemas propios o de terceros
WCF puede ser usado también en Windows XP y Windows Server 2003.  Los servicios también se pueden hospedar bajo los servicios de Internet Information Server (IIS)
EL paquete base para el uso de WCF es: System.Servicemodel

A continuación se indican unos cuantos escenarios de ejemplo:


  •          Un servicio seguro para procesar transacciones comerciales. 
  •          Un servicio que proporciona datos actualizados a otras personas, como un informe sobre tráfico u otro servicio de supervisión.
  •          Un servicio de chat que permite a dos personas comunicarse o intercambiar datos en tiempo real.
  •          Una aplicación de panel que sondea los datos de uno o varios servicios y los muestra en una presentación lógica. 
  •          Exponer un flujo de trabajo implementado utilizando Windows Workflow Foundation como un servicio WCF.
  •          Una aplicación de Silverlight para sondear un servicio en busca de las fuentes de datos más recientes.


Si bien era posible crear tales aplicaciones antes de que existiera WCF, con WCF el desarrollo de extremos resulta más sencillo que nunca. En resumen, WCF se ha diseñado para ofrecer un enfoque manejable para la creación de servicios web y clientes de servicios web.

Marcas que se deben poner a las interfaces o clases para que estén disponibles como servicios.
<OperationContract()>
Al poner estas marcas en la declaración de un método se hace disponible para ser usada como servicio WCF
<ServiceContract()>
Indica que esta clase o interface se comporta como un contrato de servicio en una aplicación

Hospedar un Servicio
Para hospedar un servicio se necesitas de 3 datos necesarios:

1.       Address (Dirección del Extremo)
La dirección del servicio

2.       Binding (Enlace del extremo)
Como se configura el servicio (HTTP, HTTPS, TCP, u otros protocolos) como acceder

3.       Contrato (Contrato que el extremo está exponiendo)
La definición del servicio.

Todo esto se agrega en un punto de conexión (ENDPOINT)

ENDPOINT
Identifica a un recurso o una dirección de red. Ésta es una clase abstract.



EJEMPLO SIMPLE DE USAR WCF
Pasos para crear un servicio sencillo.
1.       Creamos el contrato que será expuesto al cliente.

using System;
// Add the using statement for the System.ServiceModel namespace
using System.ServiceModel;
namespace Microsoft.ServiceModel.Samples
{
  //Define a service contract.
  [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
  public interface ICalculator
  {
    //Create the method declaration for the contract.
    [OperationContract]
    double Add(double n1, double n2);
    [OperationContract]
    double Subtract(double n1, double n2);
    [OperationContract]
    double Multiply(double n1, double n2);
    [OperationContract]
    double Divide(double n1, double n2);
  }
}
  
2.       Ahora creamos la implementación de la clase usando la interface definida:
 
public class CalculatorService : ICalculator
{
public double Add(double n1, double n2)
{
    double result = n1 + n2;
    Console.WriteLine("Received Add({0},{1})", n1, n2);
    // Code added to write output to the console window.
    Console.WriteLine("Return: {0}", result);
    return result;
}
 
public double Subtract(double n1, double n2)
{
    double result = n1 - n2;
    Console.WriteLine("Received Subtract({0},{1})", n1, n2);
    Console.WriteLine("Return: {0}", result);
    return result;
}
 
public double Multiply(double n1, double n2)
{
    double result = n1 * n2;
    Console.WriteLine("Received Multiply({0},{1})", n1, n2);
    Console.WriteLine("Return: {0}", result);
    return result;
}
 
public double Divide(double n1, double n2)
{
    double result = n1 / n2;
    Console.WriteLine("Received Divide({0},{1})", n1, n2);
    Console.WriteLine("Return: {0}", result);
    return result;
}
 
}

Como se ve a la clase no se ha hecho nada, y puede ser usada como si fuera una clase normal usando su respectiva DLL. Pero también esta clase definida puede ser expuesta como servicio

3.       Luego lo que tenemos que hacer es hacer que este servicio esté disponible en para que terceros puedan consumirlos. Para hacer esto debemos de hostearlo o ponerlo en IIS (Internet Information Server). Es mucho mejor ponerlo en IIS por razones de seguridad, concurrencia de usuarios, sobre todo cuando los servicios más extensos.

4.       Cuando creamos un nuevo proyecto que será como el que hostee debemos hacer referencia al proyecto donde están las clases de nuestro servicio. Un ejemplo de como hostear sería:
// Step 1 of the address configuration procedure: Create a URI to serve as the base address.

Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service");
   // Step 2 of the hosting procedure: Create ServiceHost

ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);

            try
            {
                // Step 3 of the hosting procedure: Add a service endpoint.
                selfHost.AddServiceEndpoint(
                    typeof(ICalculator),
                    new WSHttpBinding(),
                    "CalculatorService");


                // Step 4 of the hosting procedure: Enable metadata exchange.
                ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                selfHost.Description.Behaviors.Add(smb);

                // Step 5 of the hosting procedure: Start (and then stop) the service.
                selfHost.Open();
                Console.WriteLine("El servicio ya se inicio.");
                Console.WriteLine("Press <ENTER> to terminate service.");
                Console.WriteLine();
                Console.ReadLine();

                // Close the ServiceHostBase to shutdown the service.
                selfHost.Close();
            }
            catch (CommunicationException ce)
            {
                Console.WriteLine("An exception occurred: {0}", ce.Message);
                selfHost.Abort();
            }

5.       Configuracion de Servicio: Se puede agregar la configuración del servicio mediante el archivo de configuración o mediante código. Es mejor hacerlo mediante archivo de configuración para que cuando llevemos a IIS, sepa leerlo, mediante el app.config.
6.       En el archivo de configuración agregamos una etiqueta  <system.serviceModel>. Sin embargo podemos usar una herramienta para que agrege estas configuraciones que se llama WCF Services Configuration Editor.


Tomar en cuenta que cuando vamos a hacer que una librería sea para distribución como servicio debemos hacer la referencia en el proyecto la librería System.RunTime.Serialization esto permite convertir un formato de pueda ser enviado a través del servicio. La serialización es el proceso mediante el cual se convierte un objeto o un gráfico de objetos en una secuencia lineal de bytes para su almacenamiento o transmisión a otra ubicación. La deserialización es el proceso mediante el cual se recoge la información almacenada y se vuelven a crear objetos a partir de la misma. También debemos agregar System.ServiceModel
Cuando creamos el proyecto de Host debemos hacer la referencia a System.ServiceModel desde el menú del árbol de proyectos.
7.       Luego, hacemos correr el proyecto del servicio en el host y procedemos a crear un nuevo proyecto  de tipo consola que servirá de consumidor de servicio. Agregamos un nuevo proyecto con la referencia a System.ServiceModel
8.       Luego con la herramienta de consola de comandos de Microsoft visual studio  navegamos a la solución recién creada y generamos el archivo de configuración y el proxy. Esto generará código de modelo del servicio para el cliente a partir de documentos del metadatos

svcutil.exe /language:cs /out:generatedProxy.cs /config:app.config http://localhost:8000/ServiceModelSamples/service

9.       Agregue el proxy generado al proyecto de cliente en Visual Studio, haga clic con el botón secundario en el proyecto de cliente en el Explorador de soluciones, y seleccione Agregar y Elemento existente. Seleccione el archivo generatedProxy.cs generado en el paso anterior.
10.   Asegurese que el archivo de configuración apunte correctamente a la dirección del servicio.
11.   Una vez que haya creado el archivo app.config y generatedProxy.cs ponemos este código en Program.cs del mismo proyecto:
static void Main(string[] args)
        {
            CalculatorClient client = new CalculatorClient();

            double value1 = 100.00D;
            double value2 = 15.99D;
            double result = client.Add(value1, value2);
            Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);

            // Call the Subtract service operation.
            value1 = 145.00D;
            value2 = 76.54D;
            result = client.Subtract(value1, value2);
            Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);

            // Call the Multiply service operation.
            value1 = 9.00D;
            value2 = 81.25D;
            result = client.Multiply(value1, value2);
            Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);

            // Call the Divide service operation.
            value1 = 22.00D;
            value2 = 7.00D;
            result = client.Divide(value1, value2);
            Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);

            //Step 3: Closing the client gracefully closes the connection and cleans up resources.
            client.Close();


            Console.WriteLine();
            Console.WriteLine("Press <ENTER> to terminate client.");
            Console.ReadLine();
        }

12.   Finalmente probamos y debería quedar así: