lunes, 23 de enero de 2017

Introducción a las llamadas asincronas con WCF

Cada vez es más importante no bloquear nuestra interface de usuario, para conseguir una mayor fluidez en nuestras aplicaciones. Cuanto menos tiempo utilicemos un recurso, más fluido funcionarán nuestra aplicaciones.

Una forma sencilla que ofrece WCF desde su aparición es simplemente no esperar al resultado de una llamada. Para ello existe el parámetro IsOneWay del atribute OpeatonContractAttribute. Con esto el cliente no esperará a recibir una respuesta del servidor.

[OperationContract(IsOneWay = true)]
void Echo();

Como es de esperar, al especificar IsOneWay, nuestro método no puede devolver nada y hay que definirlo como void.

En una próxima entrada explicaré como usar asyn/await. Una forma más avanzada de hacer llamadas asíncronas sin bloquear los recursos de la máquina tanto en el cliente como en el servidor.

jueves, 12 de enero de 2017

Traducir al ingles mensages de excepciones

Cuando se produce una excepción que no conocemos su causa una forma de obtener informaciones es utilizar google o bing para buscar información. La cual suele ser mucho más abundante en ingles que en cualquier otro idioma. Una forma de obtener estos mensajes en ingles es utilizar un Windows en ingles o cambiar la configuración regional. Pero hay una forma más sencilla de obtener este mensaje sin necesidad de estar cambiando la configuración de nuestra maquina. Y es introduciendo un nuestro código un cambio de idioma.


Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");           Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

Tras esta líneas todas las excepciones aparecerán en ingles.

No olvidéis eliminar las líneas tras solucionar el problema, ya que no solo se cambia el idioma en el que aparecen las excepciones, si no toda la configuración regional, como hora, formato moneda, puntuación de decimales, ...

lunes, 9 de enero de 2017

Introducción a WCF

En alguna ocasiones me ha tocada mantener aplicaciones que utiliza las Windows Communication Foundation como herramienta de comunicación y siempre he tenido que sufrir lo complicado que es su mantenimiento, debido a la utilización de asistentes. Estos asistentes suelen funcionar muy bien para crear el servicio, ya que te crea todos los objetos de intercambio de datos. Pero complican terriblemente su mantenimiento. Desaprovechan la capacidad de .Net de funcionar en cualquier plataforma y compartir código. Y es muy complicado implementar pruebas unitarias.

Con esta entrada voy a iniciar una serie en la que trataré de explicar cual es la forma de sacar toda la potencia que tiene WCF.

Lo primero que hay que hacer para definir un servicio es crear una interfase que lo defina. Para que WCF la entienda se deberá marcar la interface con el atributo ServiceContractAttribute y cada propiedad con OperationContractAttribute.

[ServiceContract]
public interface IOperacioens
{
   [OperationContract]
   double Plus(double x, double y);
}


Y definimos la clase en el servidor que implementa la interfase.

public class OperacioensNetService : IOperacioen
{
   public double Plus(double x, double y)
   {
      return x + y;
   }
}
Construimos nuestra clase de servicio heredando de ServiceHost. En la que utilizamos la clase BasicHttpBinding para definir un servicio SOAP sobre Http.

public sealed class OperationsServiceHost : ServiceHost
{
   public OperationsServiceHost(Uri baseAddresses)
        :this(typeof(OperationsNetService), baseAddresses)
   {
   }

   public OperationsServiceHost(Type serviceType, params Uri[] baseAddresses)
        :base(serviceType, baseAddresses)
   {
        CreateBinding();
   }

   private void CreateBinding()
   {
        Binding binding = new BasicHttpBinding();
        base.AddServiceEndpoint(typeof(IOperations), binding, string.Empty);
    }
}

Creamos la clase de conexión en la parte del servidor, la cual nos creará el canal de comunicaciones.


public class OperationsConnection : IDisposable
{
    private ChannelFactory<IOperations> mFactory = null;

    public ChannelFactory<IOperations> Factory
    {
       get { return mFactory; }
    }

    private IOperations mChannel;

    public IOperations Channel
    {
       get
       {
           if (mChannel == null)
           {
              mChannel = Factory.CreateChannel();
           }
           return mChannel;
       }
    }

    public OperationsConnection(string service)
    {
        Binding binding;

        binding = new BasicHttpBinding();
        ContractDescription contract = ContractDescription.GetContract(typeof(IOperations));

        ServiceEndpoint endpoint = new ServiceEndpoint(
                    contract,
                    binding, new EndpointAddress(service));

        mFactory = new ChannelFactory<IOperations>(endpoint);
    }

    #region IDisposable
    public void Close()
    {
        if (mFactory != null)
        {
            mFactory.Close();
        }
     }

     public void Dispose()
     {
        Dispose(true);
        GC.SuppressFinalize(this);
     }

     protected virtual void Dispose(bool disposing)
     {
         if (disposing)
         {
             this.Close();
         }
     }
     #endregion
    }

Ya tenemos todas las piezas. Ahora solo nos queda montarlas. Para ello tenemos dos opciones en el lado del servidor. Montar nuestro propio Host auto hospedado. Lo cual nos permitirá crear un servidor con cualquier tipo de aplicación, ya sea aplicación de consola, servicio NT o una aplicación Windows. Utilizaremos la clase OperationsServiceHost anteriormente creada. En nuestro ejemplo se expondrá un servicio que escucha por el puerto 9085.

using (var operationsService = new OperationsServiceHost(
        new Uri("http://localhost:9085/OperationsService.svc")))
{
     operationsService.Open();
     Console.ReadLine();
}

Otra forma es hospedar nuestro servicio en un servidor IIS. Lo que nos permitirá aprovechar el del Pool de conexiones y el reciclaje de servicios de los que dispone el IIS. Para montar el servicio tendremos que crear un fichero con extensión svc, en el que se define el ServiceHost y una clase HostFactory que se encargará de crear la instancia del ServiceHost. Se definirá de la siguiente manera.



<%@ ServiceHost
     Service="OperacionesWCF.Server.OperationsNetService"
     Factory="OperacionesWCF.Server.OperationsServiceHostFactory" %>

Ya solo nos queda hacer las llamadas a nuestro servicio desde una aplicación cliente. Lo cual aremos con la clase anteriormente creada OperationConnection. La cual tiene una propiedad Channel, la cual nos devolverá una instancia virtual al servicio en el servidor.




using (OperationsConnection connection =

                new OperationsConnection(url))

{
    IOperations operations = connection.Channel;
    Console.WriteLine(operations.Plus(345, 23));
}


Podéis descargar un ejemplo en:
https://github.com/andrechi1/Blog-Examples/tree/master/OperationsWCF