WCF TIPS - Como generar una descarga http estándar y hostearla desde un servicio

por maxi  20. septiembre 2010

    Objectivo: Crear un ejemplo de servicio con WCF que permita a un navegador descargar un archivo por http en forma estándar.

    Características del servicio:

    • Self-Host: En este caso va a ser Self-host  en una aplicacion Winforms asi puede ser hosteado en cualquier maquina sin necesidad de configurar un IIS.

    • REST: No se utilizara SOA, ya que REST es más liviano dado que el mensaje no tiene toda la información del Envelope SOAP.

      Streamming: El servicio enviará el archivo en mediante Streamming lo que permite manejar archivos grandes.

    • Multithreading: el servicio no será Single es decir una instancia del servicio atenderá cada llamada, de esta forma el servicio no encolara las solicitudes si no que podrá atender varias descargas al mismo tiempo y a diferentes clientes.

      Lo primero que haremos será crear el contrato, al que llame IDownloadService que contiene el método DownloadFileHttp, el cual recibe el path y el nombre del archivo para descargar y retornara el Stream.

      Esta claro que no es ideal recibir el path del archivo en el servicio, pero lo hice para ejemplificar como recibir varios parametros ya que este servicio utiliza REST por lo cual el servicio recibe los parametros en forma de query string. El atributo WebGet precisamente nos permite definir que el servicio recibira la solicitud mediante una url de la siguiente forma:

                                       DirecciónBase           / download    / path / fileName

      P.e.: http://localhost:9000/DownloadService / download    / C:@mp3  /   tema.mp3

       
           [ServiceContract]
          public interface IDownloadService
          {
              [OperationContract]
              [WebGet(UriTemplate = "download/{path}/{fileName}")]
              Stream DownloadFileHttp(string path, string fileName);
          }
       

      Una vez definido el contrato vamos  a implementarlo de la siguiente manera:

       
        [ServiceBehavior(
              //Cada solicitud crea una nueva instancia de StreamerSvc y se recicla despeus de la llamada 
              //De esta forma las llamadas no se encolan se puede atender a varios clientes
              InstanceContextMode = InstanceContextMode.PerCall,
              //La instancia del servicio es multi threaded
              //Los threads pueden llamar a cualquier operacion del servicio en cualquier momento
              //Multiple implica que le programador tiene que manejar la sincronizacion con locks
              //Pero como el servicio no maneja estados, p.e. variables o atributo de clase no me afecta
              ConcurrencyMode = ConcurrencyMode.Multiple,
              //Esta propiedad hay que setearla en este ejemplo ya que el servicio esta siendo hosteado en una aplicacon Winforms
              //Implica que todas las llamadas al servicio correran en el mismo thread de la UI que creo el servicio (new ServiceHost(...)))
              //La pongo en false para evitar deadlocks ya que por defecto es true
              UseSynchronizationContext = false)]    public class DownloadSvc : IDownloadStream
          {
              public Stream DownloadFileHttp(string path, string fileName)
              {
      //Truco para poder poner el path en la url solo para este ejemplo
                      path = path.Replace("@", @"\");@", @"\");File does not exists!");application/download";content-disposition", string.Format("attachment;filename=\"{0}\"", fileName));
                      fileName = fileName.Replace("
                      path = Path.Combine(path, fileName);
       
                      if (!File.Exists(path))
                      {
                          throw new FaultException("
                      }
              
                      //Abrimos el archivo 
                      var fileStream = File.OpenRead(path);
       
                      //Configurar Headers para el cliente p.e. un browser
                      var headers = WebOperationContext.Current.OutgoingResponse.Headers;
                      WebOperationContext.Current.OutgoingResponse.ContentType = "
                      headers.Add("
                      headers.Add("content-length", fileStream.Length.ToString());
       
               //Retonranos FileStream
                      return fileStream;
              }}
        

      Muy bonito pero para que todo esto funcione correctamente debemos configurar nuestro servicio. Para esto vamos a setear las siguientes entradas en el config:

       
      <?xml version="1.0" encoding="utf-8"?>
      <configuration>
               <system.serviceModel>
                         <bindings>
                                  <mexHttpBinding>
                                            <binding name="MetadataBinding" />
                                  </mexHttpBinding>
                                  <webHttpBinding>
                                            <binding name="DownloadBinding" sendTimeout="00:10:00" maxBufferPoolSize="2147483647"
                                             maxReceivedMessageSize="2147483647" transferMode="Streamed">
                                            </binding>
                                  </webHttpBinding>
                         </bindings>
                         <services>
                                  <service behaviorConfiguration="ServiceBehavior" name="StreamerSvcHost.StreamerSvc">                             
                                            <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="MetadataBinding"
                                             name="MetadataEndpoint" contract="IMetadataExchange" />
                                            <endpoint address="FileSvc" behaviorConfiguration="RestBehavior"
                                             binding="webHttpBinding" bindingConfiguration="DownloadBinding"
                                             name="DownloadEndpoint" contract="StreamerSvcHost.IDownloadService" />
                                            <host>
                                                     <baseAddresses>
                                                              <add baseAddress="http://localhost:9000/" />
                                                     </baseAddresses>
                                            </host>
                                  </service>
                         </services>
                         <behaviors>
                                  <endpointBehaviors>
                                            <behavior name="RestBehavior">
                                                     <webHttp />
                                            </behavior>
                                  </endpointBehaviors>
                                  <serviceBehaviors>
                                            <behavior name="ServiceBehavior">
                                                     <serviceMetadata httpGetEnabled="true" />
                                                     <serviceDebug includeExceptionDetailInFaults="true" />
                                                     <dataContractSerializer maxItemsInObjectGraph="2147483647" />
                                            </behavior>
                                  </serviceBehaviors>
                         </behaviors>
               </system.serviceModel>

      </configuration>

       

        Lo destacable es lo siguiente:

        • El endpoint deberá tener un webHttpBinding, esto permite exponer el servicio para ser accedido mediante HTTP requests  en lugar de mensajes SOAP.

        • El binding se deberá configurar con TransferMode = Streamed

        • El endpoint deberá tener configura un EndpointBehavior agregándole le elemento webHttp, para que un cliente pueda comunicarse por http con el servicio este debe tener asociado este comportamiento.

        Tags: , , , , , ,

        WCF

        WCF Tips - Clases definidas en el servicio que no aparecen en el proxy del cliente?

        por maxi  14. septiembre 2010

        Cuando generamos una referencia a un servicio en un proyecto de Visual Studio se genera un proxy con todos los métodos definidos en el ServiceContract y las clases definidas como DataContract.
        Los DataContract aparecen en el proxy cuando son recibidos o retornados por algún método de la interfaz. En caso contrario no se generará ya que no aparece en la metadata del servicio.

        Si por algun caso en particular, nosotros utilizamos alguna clase o un enum en un proceso del servicio y este no es recibido ni retornado por ningun metodo y quisieramos utilizarlo del lado, es decir en el cliente,
        estaríamos obligados a duplicarlos manualmente. Por lo tanto vamos a querer que se generen en el proxy del cliente y para lograr esto debemos hacer lo siguiente:

        Primero, generamos una clase que va a contener un método que retornará la lista de clases que serán agregadas a la metadata del servicio. Luego implementamos el método correspoindiente el cual debe retornar una lista de Types, IEnumerable<Type>, y recibirá como parametro un ICustomAttributeProvider. Internamente creamos una lista donde agregamos los Type deseados como se muestra a continuación:

         

         

         

           1:      public static class EnumHelper
           2:      {
           3:          /// <summary>
           4:          /// Obtiene una lista de tipos conocidos que se requieren publicar al cliente
           5:          /// </summary>
           6:          /// <param name="provider"></param>
           7:          /// <returns></returns>
           8:          public static IEnumerable<Type> ObtenerTiposConocidos(ICustomAttributeProvider provider)
           9:          {
          10:              //Incluir los tipos que se requiere ver en el cliente
          11:              var tiposConocidos = new List<Type>
          12:                                              {
          13:                                                  typeof (CodigosMovEnum),
          14:                                                  typeof (Etc)
          15:                                              };
          16:   
          17:              return tiposConocidos;
          18:          }
          19:      }


         

        Segundo, debemos agregar el Atributo ServiceKnownType a nuestro contrato de servicio. Y vamos a pasar como parámetros, primero el Metodo que retorna los Types de las clases que serán agregadas

        en la metadata del servicio y luego, el Type de la clase que contiene dicho método que en este caso es EnumHelper como se muestra a continuación:

         

           1:      [ServiceKnownType("ObtenerTiposConocidos", typeof(EnumHelper))]
           2:      [ServiceContract]
           3:      public partial interface IMiServiceContract
           4:     {    
           5:     }

         

        Luego compilamos el servicio y al actualizar la referencia al proxy del cliente apareceran estas nuevas clases.

         

        Tags: ,

        WCF Tips - Enum definirlo en el servicio y utilizarlo en el cliente

        por maxi  14. septiembre 2010

        Para utilizar un enum simplemente lo definimos y agregamos el atributo DataContract. A cada valor del enum le definimos el atributo EnumMember.

        De esta forma si este enum se recibe como parámetro o es retornado por un metodo del servicio, se generará en la referencia al servicio del cliente.

         

            [DataContract]
        public enum CodigosMovEnum
        {
        [EnumMember]
        Ninguno = 0,

        [EnumMember]
        AEntregar = 1,

        [EnumMember]
        ACumplir = 2,

        }

        Tags: ,

        WCF

        Que hay de nuevo en VS2010?

        por Daniel Laco  4. marzo 2010

        Ya se viene la liberación de la versión final de Visual Studio 2010 y .NET 4.0 y uno siempre quiere tener una vista rápida de los cambios, agregados, etc.

        En http://msdn.microsoft.com/en-us/library/bb386063(VS.100).aspx pueden encontrar un listado de todos los temas nuevos de esta plataforma.

         

        Tags: , , , ,

        .NET | ADO.NET | ASP.NET | Entity Framework | Visual Studio | WCF | WinForms

        Lectura recomendada “SOA in Practice” de Nicolai M. Josuttis

        por maxi  22. enero 2010

         

        Recientemente he comenzado a leer este libro y la verdad es que quisiera recomendarlo. Tanto para quienes estén por arrancar con un proyecto SOA como para quienes ya estén plenamente involucrados con este tipo de arquitectura, como es mi caso. La verdad es que me siento representado por las vivencias del autor y me parece importante compartir algunas conclusiones iniciales.

        Aclaro que en esta primera parte solo me voy a referir a temas conceptuales y de gestión, no a detalles técnicos ni tecnologías específicas.

         

        Que es SOA?

        En este caso coincido totalmente cuando el autor dice que hay infinidad de definiciones y lo principal es quedarse con la idea importante de SOA.

        SOA es un paradigma para el diseño de la arquitectura de nuestros sistemas que permite orquestar y mantener grandes sistemas distribuidos. Para entender SOA hay que entender las características de los grandes sistemas, donde tenemos que luchar con los viejos sistemas legados, la mayoría de los cuales inicialmente van a seguir operativos. No podemos hacer todo desde cero desde el comienzo y por esto vamos a tener que trabajar en conjunto las plataformas viejas y temas de compatibilidad.


        Por qué SOA?

        SOA permite que los sistemas de la organización sean flexibles mientras crecen,  interoperar y orquestarse de forma más sencilla.  Esto es referido tanto a los sistemas internos de la organización como con sistemas externos como ser clientes, proveedores, gobierno, etc.

        Determinadas  organizaciones cuentan con sistemas grandes, complejos y heterogéneos, es decir,  utilizan una variedad de tecnologías diferentes  y con mucha longevidad. Eventualmente el costo de mantenimiento ya sea para incorporar nuevas funcionalidades como para interconectarse con otros sistemas se hace muy grande. Principalmente debido a la cantidad de “conexiones” que estos sistemas utilizan para interactuar con otros o para implementar diferentes funcionalidades y  donde cada uno puede usar tecnologías muy diferentes.

         

        Conceptos

        El autor presenta como los elementos más importantes:

        • Los Servicios, son unidades que contienen funcionalidad de negocio, construidos sobre los principios y  pilares de este estilo de arquitectura y que pueden ser implementados con diferentes tecnologías y plataformas.

         

        • Una infraestructura específica, llamada Enterprise Service Bus (ESB). El ESB está formado por la infraestructura que permite a los sistemas interoperar. Si bien parece complicado, en realidad es simplemente una abstracción, es una línea base, común para interconectar nuestros servicios y consumirlos.   Son los puntos de conexión a nuestros servicios, sus detalles tecnológicos, interfaces, seguridad, framework, etc. En otras palabras, soporta los conceptos de interoperabilidad y desacople. El desacople es un concepto que permite reducir las dependencias entre los sistemas para disminuir los efectos de las modificaciones y de los fallos. Para lograrlo, se debe pagar un precio  que consiste en aumentar la complejidad. Esto se traduce en más dificultad de desarrollo, mantenimiento y debug.


         

        Figure 1 Enterprise Service Bus

         

        • Políticas y procesos, que permiten crear y mantener estos servicios que pueden ser heterogéneos y que tienen diferentes “owners”.

         

        No se debe perder de vista que cuando trabajamos con SOA,  tenemos una arquitectura que abarca servicios, infraestructura de redes, servidores, seguridad, políticas y procesos para su gestión, etc. Todo esto debe estar a la medida del desafío.

        Hay que tener en cuenta que una arquitectura distribuida es compleja por sí misma y abarca muchas disciplinas de IT. Es por esto que considero importantísimo a la hora de aplicar SOA hacer una clara definición de los roles, equipos involucrados y políticas de colaboración.

        No sólo vamos a tener equipos de desarrollo, es necesario tener un equipo de arquitectura encargado del ESB, un equipo que se ocupe de definir políticas y procesos,  un equipo de infraestructura (Administradores de servidores, redes y seguridad). También se debe definir los referentes tecnológicos (Conocedores de las plataformas, lenguajes de programación, etc.) y los sponsors (Gerentes, Líderes de proyecto, etc.), que son quienes nos brindan los recursos (tiempo y dinero).

        Un concepto interesante que introduce el autor es el de owner, como el  equipo que  dueño del servicio está encargado de su desarrollo, que aplica las políticas y que utiliza los procesos definidos. Cada owner maneja diferentes presupuestos, tiempos, visiones e intereses que hay que considerar. Y es necesario que estos owners colaboren con otros para poder orquestar y ampliar las funcionalidades de sus sistemas. Esta colaboración no sólo abarca a los owners si no también al equipo de arquitectura y al personal de infraestructura. Por esto las políticas y los procesos son iguales o más importantes que el conocimiento de la tecnología.


        Como dice el autor “…Una vez que se comprende como implementar SOA, no es difícil,  pero toma tiempo y coraje (OK, entonces es difícil). Cuesta mucho esfuerzo ayudar a la gente a que comprenda el paradigma (comenzando por uno mismo) y si no estás dispuesto a hacer el esfuerzo fallarás…”

         

        Gobernance

        El autor destaca los siguientes puntos para la administración SOA:

        • Se necesita tener un equipo central para determinar los aspectos generales de SOA  de la organización. El objetivo debe ser lograr la descentralización de los sistemas grandes.

         

        • Se debe contar con el personal adecuado y con experiencia en sistemas grandes, de manera que puedan tomar decisiones prácticas relacionadas con ellos. Los requerimientos de los equipos de negocio son quienes lo conducen y deben considerarse como sus proveedores.

         

        • No eNo es necesario considerar desde el comienzo la administración de los servicios. Se puede pensar cómo administrarlos cuando se logren tener muchos en funcionamiento. Es decir, no es necesario crear o pensar en toda la infraestructura desde un inicio si no que deben crecer juntos.


        • El  CEO y del CIO (Chief Information Officer) deben apoyar el concepto de SOA. Es decir, se debe contar con el apoyo de la dirección de la organización y de la gerencia de sistemas, para tomar las decisiones adecuadas y que provean el suficiente tiempo y dinero. Tener suficientes fondos a corto plazo no es lo importante. Se necesita dinero a largo plazo dado que cortar el presupuesto de SOA cuando se ha hecho la mitad de las tareas es una receta para el desastre.

         

        Primeras conclusiones

        SOA es un paradigma que tiene que ayudar a la gente de IT a ser flexibles, esto significa brindar soluciones a los requerimientos del negocio oportunamente. Mantener e integrar sistemas grandes y heterogéneos, y sistemas legados hasta que sean reemplazados. Para lograr esto la organización se debe alinear y también los roles, procesos, etc. ya que todos estos aspectos están relacionados.an>

        SOA no es una herramienta o receta que se pueda aplicar para “hacer que todo funcione”. Es un paradigma que se debe desarrollar y aplicar en la organización en su conjunto.

        Tags: , ,

        SOA

        Como cerrar correctamente un proxy WCF

        por Emmanuel  17. marzo 2009
        Teniendo en cuenta que un proxy WCF se deriva de ClientBase<TChannel>, y que éste implementa IDisposable, la mejor manera de utilizarlo pareciera ser:
               try
               {
                   using (var proxy = ProxyFactory.ObtenerProxy())
                   {
                       //Utilizar el proxy
                   }
               }
               catch (Exception ex)
               {
                   throw;
               }
         
        Esta forma de utilización puede llevarnos a un error WCF cuando ocurre una excepción y el canal queda en estado “Faulted”, impidiendo cerrar el proxy.
         
        Si accedemos por Reflection a la implementación de IDisposable observamos:
         
               void IDisposable.Dispose()
               {
                   this.Close();
               }
         
        Esta implementación no contempla el estado del proxy antes de llamar a Close(), de manera que ante cualquier error ocurrido al intentar cerrar el proxy recibiremos una excepción.
         
        Una manera de corregir este comportamiento es creando una extensión:
         
               public static void CloseExt(this SvcClient proxy)
               {
                  if (proxy != null)
                  {
                      var checkClosedState =
                          CommunicationState.Closed | CommunicationState.Closing;
         
                      if (proxy.State == CommunicationState.Faulted)
                      {
                          proxy.Abort();
                      }
                      else if (proxy.State != checkClosedState)
                      {
                          proxy.Close();
                      }
                  }
              }
         
        Y para utilizar la extensión el código se modificaría a:
         
                 SvcClient proxy = null;
         
                try
                {
                   proxy = ProxyFactory.ObtenerProxy;
         
                   //Utilizar el proxy
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    proxy.CloseExt();
                }
         
        De esta manera siempre se llama a la extensión CloseExt(), la que se encarga de cerrar o abortar el proxy según su estado, impidiendo que se genere una excepción por intentar cerrar un proxy en estado “Faulted”.

         

         

        Tags:

        WCF

        Introducción a WCF - Parte 5

        por Maxi Guillén - Daniel Laco  9. febrero 2007

        Introducción a Windows Communication Foundation

        PARTE 5

        Otras Facilidades de WCF

        Transacciones

        WCF nos brinda la posibilidad de realizar transacciones con los servicios. Estas transacciones pueden también ser distribuidas, cuando se comparten con más de un servicio.

        Para habilitar las transacciones:

        • Necesitamos utilizar un Binding adecuado
        • Seleccionar el protocolo (WS-AtomicTransacction , OLE Transactions)
        • Es posible configurar Timeouts y Niveles de Aislamiento utilizando parámetros de ServiceBehavior
        • Habilitar las funcionalidades de transacciones y el comportamiento al completarse la transacción utilizando parámetros de OperationBehavior
        • Podemos tener acceso al contexto de la transacción mediante la propiedad “Transaction.Current”

         

         

        Ejemplo de Transacción:

        En el servicio:

        [ServiceContract(SessionMode = SessionMode.Required)]
        [BindingRequirements(
        TransactionFlowRequirements = RequirementsMode.Required)]
        public interface IClienteManager
        {
                [OperationContract()]
                [TransactionFlow(TransactionFlowOption.Allowed)]
                List<Cliente> DameClientes();
        
                [OperationContract()]
                [TransactionFlow(TransactionFlowOption.Allowed)]
                void ModificarCliente(int id, 
                string nuevoNombre, string nuevoApellido);
        
                [OperationContract()]
                Cliente BuscarCliente(int id);
        }
         
        [ServiceBehavior(TransactionIsolationLevel = 
        System.Transactions.IsolationLevel.ReadUncommitted,
         InstanceContextMode = InstanceContextMode.Single)]
        public class ClienteManager : IClienteManager
        {
        
            [OperationBehavior(TransactionScopeRequired = true, 
            TransactionAutoComplete = true)]
             public void ModificarCliente(int id, <
             span class="kwrd">string nuevoNombre, string nuevoApellido)
              {
                    ...
              }
        }
        

        En el cliente:

        try
        {
            using (TransactionScope tx = new 
            TransactionScope(TransactionScopeOption.Required))
            {
                //código de la transacción
                tx.Complete();
            }
        }
        catch(Exception e)
        {
            Console.WriteLine("ERROR: {0}", e.Message);
        }

        Modo de transmisión

         Buffer vs Stream: si los mensajes se envían utilizando buffer (patrón duplex) el receptor los aloja en un buffer en memoria hasta que se complete la transmisión y no es posible acceder a los datos hasta que el mensaje sea recibido completamente. En cambio si utilizamos un stream (request-reply) los headers se colocan en un buffer y el body se expone como stream para que pueda ser accedido en partes pequeñas mientras aún se está transmitiendo. Se puede utilizar stream como parámetro o devolverlo como resultado y es ideal para la transmisión de mensajes grandes. Por defecto http, tcp/ip y named pipes utilizan buffer. Este modo de trasferencia se especifica al crear el objeto binding de nuestro endpoint.

         

        Ejemplo:

        TcpTransportBindingElement transporte = new TcpTransportBindingElement();
        transporte.TransferMode = TransferMode.Streamed;
        BinaryMessageEncodingBindingElement codificador = new 
        BinaryMessageEncodingBindingElement();
        CustomBinding binding = new CustomBinding(codificador, transporte);
        

        Ejemplo por archivo de configuración:

        <customBinding>
           <binding name="streamBinding">
              <binaryMessageEncoding />
              <tcpTransport transferMode=”Streamed/>
           </binding>
        </customBinding>
        

        Restricciones derivadas de utilizar transferencias del tipo Stream:

        • En el contrato el parámetro o resultado stream debe ser un subtipo de Sytem.IO.Stream o implementar IXmlSerializable.
        • Mensajes confiables, transacciones y la seguridad a nivel de mensaje SOAP dependen de una transmisión tipo buffer.
        • Los Encabezados (headers) SOAP siempre utilizan buffer y no deben superar la propiedad MaxBufferSize.

        El ejemplo que mostramos a continuación es una implementación de streaming que permite escuchar música desde un cliente. La música es publicada por un servicio de WCF.

        Ejemplo del Servicio:

        [ServiceContract(Namespace = "Test", SessionMode = SessionMode.Allowed)]
        public interface IStream
        {
            [OperationContract()]
                Stream Escuchar(string archivo);
                [OperationContract()]
                List<string> DameTemas();
        }
        
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
        public class StreamMusica : IStream
        {
                [OperationBehavior()]
                public Stream Escuchar(string archivo)
                {
                string mainPath = @".\Temas\";
                    mainPath += archivo;
                    FileStream fs = new FileStream(mainPath, 
                    FileMode.Open, FileAccess.Read);
                    return fs;
                }
        
                [OperationBehavior()]
                public List<string>  DameTemas()
                {
                string mainPath = @".\Temas\";
                    List<string> temas = new List<string>();
        
                   foreach (string archivo in Directory.GetFiles(mainPath,"*.wav"))
                   {
                       string nombre = Path.GetFileName(archivo);
                            temas.Add(nombre);
                }
        
                    return temas;
                }
        }

        App.Config:

        <?xml version="1.0" encoding="utf-8"?>
        <configuration>
         
            <system.serviceModel>
                <behaviors>
                    <serviceBehaviors>
                        <behavior name="NewBehavior">
                            <serviceMetadata httpGetEnabled="true" />
                        </behavior>
                    </serviceBehaviors>
                </behaviors>
                <bindings>
                    <basicHttpBinding>
                        <binding name="NewBinding0" maxBufferSize="65536" 
                        maxReceivedMessageSize="65536"
                            messageEncoding="Mtom" transferMode="Streamed" />
                    </basicHttpBinding>
                </bindings>
                <services>
                    <service behaviorConfiguration="NewBehavior" 
                    name="StreamService.StreamMusica">
                        <endpoint address="Stream" binding="basicHttpBinding" 
                        bindingConfiguration="NewBinding0"
                            name="ServiceEndpoint" contract="StreamService.IStream" />
                        <host>
                            <baseAddresses>
                                <add baseAddress="http://master3:8888/" />
                            </baseAddresses>
                        </host>
                    </service>
                </services>
            </system.serviceModel>
        </configuration>
        

         

        Ejemplo del Cliente:

         private void PLAYBUTTON_Click(object sender, EventArgs e)
        {
                #region Validar
                if (!ValidarArchivo())
                {
                    MsgHelper.ShowError("Debe seleccionar un archivo.");
                    return;
                }
                #endregion Validar
        
                try
                {
                    proxy = new StreamClient();
                    Player.Stream = proxy.Escuchar(bs.Current.ToString());
                    proxy.Close();
        
                    PLAYBUTTON.Enabled = false;
                    STOPBUTTON.Enabled = true;
        
                    Player.Play();
                }
                catch (Exception x)
                {
                    MsgHelper.ShowError(x.Message);
                }
        }
        

        Glosario

        WCF = Windows Communication Foundation.

        MSMQ = Microsoft Message Queuing.

        OS = Orientación a Servicios.

        OO = Orientación a Objetos.

        MTOM = Message Transmission Optimization Mechanism de SOAP.

        WSDL = Web Service Description Language.

        XSD = XML Schema Definition.

        SOAP = Simple Object Access Protocol.

        X.509 = Standard de certificados para firmar documentos y garantizar la seguridad en las comunicaciones.


        SDK: Software Development Kit (SDK).

         

        Referencias

         

        Programming Indigo, David Pallman, 2005.

        MSDN, Windows Communication Foundation, http://msdn2.microsoft.com/en-us/library/ms735119.aspx

        MSDN Magazine, Learn The ABCs Of Programming Windows Communication Foundation, http://msdn.microsoft.com/msdnmag/issues/06/02/WindowsCommunicationFoundation/

         

         

        Tags:

        WCF

        Introducción a WCF - Parte 4

        por Maxi Guillén - Daniel Laco  9. febrero 2007

        Introducción a Windows Communication Foundation PARTE 4

          Aproximación al desarrollo de servicios con WCF

         Si bien esta nota no es un tutorial, en esta parte mostraremos las diferentes partes que se pueden dar durante la programación de un servicio.

        Hay tres formas de encarar un proyecto de WCF

        • Por Código: implica crear primero el código de implementación del servicio, luego la definición del contrato y finalmente la descripción del servicio, ésta última se brinda mediante un MEX Endpoint (MetadataExchange) o archivos WSDL y XSD; no todos los tipos de clases pueden ser convertidos a un esquema XSD siendo esta su desventaja.
        • Por Contrato: implica crear primero la definición del contrato, luego la descripción del servicio. La descripción del servicio permite implementar el cliente generando código a partir de los metadatos. Finalmente se crea el Código de implementación. Esta es una aproximación ideal.
        • Sin contrato: no se considera el contrato y es ideal para trabajar a nivel de mensajes. Se deben crear los mensajes a enviar e interpretar los recibidos, se puede utilizar esta técnica si el servicio debe aceptar cualquier tipo de mensaje como por ejemplo un servicio de ruteo.

        Para las alternativas anteriores nos podemos apoyar en las facilidades de generación de código ya sea para un cliente, metadatos, etc. Esto se puede realizar a través de la herramienta SvcUtil que está disponible con el SDK, se encuentra por defecto en el path “C:\Archivos de programa\Microsoft SDKs\Windows\v6.0\Bin\” y o Visual Studio y nos permite entre otras cosas:

        1. Generación del código del cliente a partir de un servicio en ejecución o documentos de metadatos online
          • svcutil http://service/metadataEndpoint
        2. Generar tipos de Data Contracts a partir de un servicio en ejecución o documentos de metadatos online
          • svcutil /dconly http://service/metadataEndpoint
        3. Generar código en diferentes lenguajes
          • svcutil *.wsdl *.xsd /language:C#
          • svcutil /dconly *.xsd /language:VB
        4. Descargar documentos de metadatos desde un servicio en ejecución
          • svcutil /t:metadata http://service/metadataEndpoint
        5. Generar metadatos
          • svcutil myAssembly.dll
          • svcutil myServiceHost.exe /serviceName:myServiceName
        6. Mediante Visual Studio
          • Agregando una referencia a un servicio de WCF genera el Proxy para ser utilizado por el cliente.

        El desarrollo de un servicio puede ser realizado definiendo por código todas sus particularidades mediante atributos, por un archivo de configuración o una combinación de ambos. En los siguientes ejemplos mostramos las alternativas:

                 Ejemplos por Código

         [ServiceContract]
        public interface IReservacion
        {

            [OperationContract]
            iniciar(string nombre);
        }

         

         ...
        Uri direccion = new Uri("http://localhost:8080/CalculadoraService/");
        serviceHost = new ServiceHost();
        serviceHost.AddEndpoint( typeof(IMyContract), new WSProfileBinding(),direccion);
        ...

                    Ejemplos por Configuración

            Especifica varias de las características de un servicio a través de un archivo de configuración (address, binding, seguridad, comportambiento, etc). Disponemos para esto de la herramienta Service Configuration Editor referido anteriormente para asistirnos en la creación del archivo.

        <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
            <system.serviceModel>
                <services>
                    <service serviceType="MiServicio">
                        <endpoint
                            address=http://localhost:8000/ MiServicio / 
                            bindingSectionName="basicProfileBinding"
                            contractType="IMiContrato" />
                    service>
                services> 
            system.serviceModel>
        configuration>

        Pasos para crear un servicio con WCF

        1. Crear una definición una interfaz .NET (Contrato del servicio)
          [ServiceContract()]
              public interface ICalculadora
              {
                  [OperationContract()]
                  double Suma(double o1, double o2);
                  
                  [OperationContract]
                  double Resta(double o1, double o2);
                  
                  [OperationContract]
                  double Multiplicacion(double o1, double o2);
                  
                  [OperationContract]
                  double Division(double o1, double o2);
              }
        2. Implementar el Contrato y Comportamiento del servicio en una clase .NET (Tipo de Servicio)
          [ServiceBehavior()]
          public class Calculadora : ICalculadora
          {
              [OperationBehavior()]
              public double Suma(double o1, double o2)
              {
                  Console.WriteLine("Ejecutando Suma");
                  return o1 + o2;
              }
              
              [OperationBehavior]
              public double Resta(double o1, double o2)
              {
                  Console.WriteLine("Ejecutando Resta");
                  return o1 - o2;
              }
              
              [OperationBehavior]
              public double Multiplicacion(double o1, double o2)
              {
                  Console.WriteLine("Ejecutando Multiplicacion");
                  return o1 * o2;
              }
              
              [OperationBehavior]
              public double Division(double o1, double o2)
              {
                  Console.WriteLine("Ejecutando Division");
                  return o1 / o2;
              }
          }
        3. Programar el inicio del servicio
          public class CalculadoraManager
          {
              private static ServiceHost _serviceHost = null;
           
                  public static void StartService()
              {
                  Uri direccion = new Uri("http://localhost:8080/CalculadoraService/");
                  _serviceHost = new ServiceHost(
          typeof(CalculadoraService.Calculadora), direccion);
              }
          
              public static void StopService()
              {
                 if (_serviceHost.State != CommunicationState.Closed)
           {
                     _serviceHost.Close();
                     _serviceHost = null;
                 }
              }
          }
        4. Configurar característicasdel servicio en App.Config
          xml version="1.0" encoding="utf-8"?>
          <configuration>
            <system.serviceModel>
              <bindings>
                <basicHttpBinding>
                  <binding name="NewBinding0" />
                basicHttpBinding>
                <mexHttpBinding>
                  <binding name="NewBinding1" />
                mexHttpBinding>
              bindings>
              <behaviors>
                <serviceBehaviors>
                  <behavior name="NewBehavior">
                    <serviceMetadata httpGetEnabled="true" />
                  behavior>
                serviceBehaviors>
              behaviors>
              <services>
                <service name="CalculadoraService.Calculadora">
                  <endpoint address="http://localhost:8888/"
                  binding="basicHttpBinding"
                    bindingConfiguration="NewBinding0" 
                    contract="CalculadoraService.ICalculadora"/>
                  <endpoint binding="mexHttpBinding" 
                  bindingConfiguration="NewBinding1"
                      contract="IMetadataExchange" />
                service>
              services>
            system.serviceModel>
          configuration>
        5. Alojar el servicio utilizando la infraestructura WCF.
          1. Mediante un servicio de Windows
          2. En IIS
          3. Aplicación
          4. Otras

         

            Definición de Endpoint utilizando completamente la API de WCF.

         

            Definición de contrato por código mediante atributos:

        Tags:

        WCF

        Introducción a WCF - Parte 3

        por Maxi Guillén - Daniel Laco  9. febrero 2007

        Introducción a Windows Communication Foundation

        PARTE 3

         

        Comportamiento de los servicios en tiempo de ejecución

        (Service Behavior) 

        Representa las distintas características de ejecución del  servicio y se especifica como parámetros del contrato, en archivos de configuración o mediante la codificación. Permite manejo de errores, diferentes formas de instanciación  y manejo de concurrencia entre otras particularidades. 

        • Instanciación: determina como se instancian las clases que implementan un contrato.

        o        Singleton: una instancia atiende a todos los clientes.

        o        Por llamada: se crea una instancia de clase por cada mensaje de petición y luego se destruye.

        o        Sesión privada: se crea una instancia de clase por cada solicitud de un cliente.

        o        Sesión compartida: idem anterior pero los clientes pueden compartir una instancia. 

        • Concurrencia: como se relacionan las instancias con los Threads.

        o        Simple: especifica que el código del objeto servicio no puede ser ejecuto por más de un thread al mismo tiempo.

        o        Múltiple: especifica que el código del objeto servicio puede ser ejecutado por múltiples threads al mismo tiempo por lo que se deben establecer mecanismos de exclusión mutua.

        o        Reentrante:

        • Throlling: define condiciones de performance del servicio.  
        • Manejo de Errores: los errores pueden ser procesados por el programador o por el framework. También se puede reportar errores al cliente.  
        • Metadata: establece la publicación de los metadatos que brindan la descripción del servicio.  
        • Tiempo de vida: un servicio puede controlar el tiempo de vida de las sesiones de un cliente, especificando las operaciones de inicio y fin de sesión.  
        • Seguridad: establece la confidencialidad e integridad de los mensajes, autenticación, autorización, auditoría y detección de reintentos.  
        • Transacciones: el programador especifica si un servicio aceptará transacciones y el cliente controla el alcance y el tiempo de vida de una transacción.  

        Descripción del servicio 

        Un servicio puede informar al entorno sus capacidades y los requerimientos necesarios para poder interactuar con él y utiliza las siguientes especificaciones: 

        • Web Services Description Language (WSDL): formato que describe lo que puede hacer el servicio, como accederlo y donde se ubica.  
        • XML Schema (XSD): formato que describe estructuras complejas  que se pasan en los mensajes.  
        • WS-Policy: formato usado para describir las políticas del servicio. (Seguridad, Sesión, Disponibilidad)  
        • WS-MetaDataExchange (o WS-MEX): protocolo de acceso para solicitar la descripción del servicio.  

        Otras características 

        En esta parte enumeramos rápidamente algunos otros puntos de interés como ser Seguridad, Administración ,etc. 

        Lo estándares de Web Service soportados son: 

        • XML, XSD, XPath, SOAP, WSDL.  
        • WS-* architecture: WS-Addressing, WS-Policy, WS-Security, WS-Trust, WS-SecureConversation, WS-ReliableMessaging, WS-AtomicTransaction, WS-Coordination, WS-Policy, and MTOM. 

        Seguridad:

         

        • Autenticación disponible:  

        o        Usuario anónimo 

        o        Credenciales 

        o        Certificados (X.509 certificates) 

        o        Windows (Kerberos and NTLM) 

        o        User/Pass personalizados

         

        · Confidencialidad de los mensajes: 

        o        SSL 

        Administración y diagnóstico de servicios: 

        • End-to-end tracing: crea un registro de las actividades de los programas de WCF.  
        • Messaging logging: registra los mensajes enviados y recibidos.  
        • SvcTraceViewer: es una herramienta que incorpora el SDK 3.0 que permite revisar el End-to-end tracing y el Message logging.  
        • Windows Management Instrumentation: permite monitorear y controlar los programas de WCF en tiempo de ejecución.  
        • Windows Performance Counters: permite obtener estadísticas del comportamiento de los programas de WCF.  
        • SvcConfigEditor: es una herramienta que brinda una interfaz gráfica para editar archivos de configuración.

         

         

        Service Configuration Editor

         

         

         

        Tags:

        WCF

        Introducción a WCF - Parte 2

        por Maxi Guillén - Daniel Laco  9. febrero 2007

         Introducción a Windows Communication Foundation PARTE 2

        Algunos Conceptos de WCF

        Servicio: es un programa que expone sus capacidades a través de una colección de Endpoints y su descripción.

        Descripciones del servicio: se publican utilizando WSDL, XSD, WS-Policy y WS-MetaDataExchange.

        Cliente: es un programa que intercambia mensajes con uno o más Endpoints y también puede exponer sus propios Endpoints. Un cliente debe conocer la Dirección, el Contrato y el Binding de un servicio para poder comunicarse con el.

        Mensaje: representa unidad de intercambio de datos entre un Cliente y un Servicio.

         

        Podemos encontrar los siguientes patrones:

        • Simplex: mensajes de una sola vía donde no se espera respuesta alguna.
        • Duplex: mensajes de dos vías de modo asíncrono.
        • Request-Reply: mensajes de dos vías de modo síncrono, es decir se envía el mensaje y se aguarda por la respuesta.

         

         

         

        Patrones de mensajes

         

        Intermediario: la comunicación entre un cliente y un servicio puede pasar a través de otro programa, denominado servicio intermediario, que debería ser desconocido para el cliente. Este servicio no consume mensajes y es simplemente un punto por el que atraviesan los mensajes en su viaje desde el cliente hasta el servicio de destino. Las Tareas útiles que pueden realizar son:

         

        • Gateway: para hacer de puente entre redes.
        • Ruteo: permite dirigir un mensaje a uno de varios servicios de destino.
        • Firewall: puede prevenir que ciertos mensajes lleguen a un servicio.
        • Monitoreo de actividad.

         

        Ejemplo de intermediario

         

        La Estructura de un Servicio

         

        Un servicio se accede a travéz de un Endpoint (Punto de Conexión) que es el medio a través del cual interactúa con su entorno. Esá¡ formado por una dirección, un enlace y un contrato, lo que se llama habitualmente el ABC (Address, Binding, Contract) del servicio.

        • Address: es la dirección de red del Endpoint. (URI: http://localhost:8080/CalculadoraService/)

        o URI (Unifrom Resource Identifier): es una forma de especificar una la dirección de un recurso, esá¡ formada por un protocolo (Http, net.TCP, net.Pipe, net.msmq) seguido del nombre del host, puerto y path: Protoclo://Host [:Puerto][/path/[.../]]

        • Binding: especifica como un servicio se comunica con el entorno. Permite crear un stack de características para el canal de comunicaciones acorde a los requerimientos del servicio (El canal no se abre hasta que el servicio reciba el primer mensaje). Permite definir:

        o El medio de transporte (HTTP, TCP, MSMQ, etc)

        o La codificación de los datos (texto, MTOM, binario)

        o La seguridad requerida (HTTP, SOAP, Windows NTLM/Kerberos, user/pass, etc)

        o La confiabilidad de las comunicaciones (sesión)

        o El patrón de mensajes (Simplex, Duplex o Request-Reply)

        o La interoperabilidad deseada (Basic WS 1° generacion, WS-*, .Net, MSMQ)

         

         

        Características de un canal de comunicaciones

        • Contract: es una colección de operaciones, especifica lo que el Endpoint puede comunicar al entorno. Los tipos de contratos que podemos especificar son:

        o Service Contract: es una interfaz que implementa un servicio (Se publica utilizando WSDL). El Operation Contract son los métodos que forman parte de la interfaz, y que podrán ser accedidos por los clientes del servicio.

        o Data Contract: define las clases y estructuras complejas que puede retornar o recibir un servicio. Es implícito si el tipo de dato es serializable, es decir el tipo de dato se puede pasar directamente sin declararlo en el contrato. Es explícito en caso contrario y se debe especificar en un data contract (Serializacion/descerializacion) (Se publica utilizando un XML Schema). El Member Contract son los atributos o propiedades del objeto que forma parte de un data contract y podrán ser serializados.

        o Message Contract: especifica la estructura, cabecera y cuerpo, del mensaje SOAP. (Message Header y MessageBody). Nos permite definir si un atributo de una clase va viaja en la cabecera o en el cuerpo de un mensaje.

        Los tipos de bindings disponibles:

         

        Binding

        Intero-perabilidad

        Seguridad

        (Default)

        Sesión

        Transacción

        (Default)

        Duplex

        Codificación

        BasicHttpBinding

        Basic Profile 1.1

        (Ninguno),

        Transporte,

        Mensaje, Mixto

        No

        No

        n/a

        Texto, (MTOM)

        WSHttpBinding

        WS

        Transporte,

        (Mensaje),

        Mixto

        Si

        (No)

        Si

        n/a

        Texto, (MTOM)

        WSDualHttpBinding

        WS

        (Mensaje),

        Ninguno

        Si

        (No)

        Si

        Si

        Texto, (MTOM)

        WSFederationHttpBinding

        WS - Federation

        (Mensaje),

        Mixto,

        Ninguno

         

        (No)

        Si

        No

        Texto, (MTOM)

        NetTcpBinding

        .Net

        (Transporte),

        Mensaje,

        Ninguno,Mixto

        SI

        (No)

        Si

        Si

        Binaria

        NetNamedPipeBinding

        .Net

        (Transporte),

        Mensaje,

        Ninguno,Ambos

        Si

        (No)

        Si

        Si

        Binaria

        NetMsmqBinding

        .Net

        Ninguno,(Transporte)

        No

        (No)

        Si

        No

        -

        NetPeerTcpBinding

        Peer

        Mensaje,

        (Transporte),

        Ambos

        No

        (No)

        Si

        -

        MsmqIntegrationBinding

        MSMQ

        (Transporte)

        No

        (No)

        Si

        n/a

        -

        Tags:

        WCF

        Acerca de los Autores

        Este es el blog del equipo de VEMN SA 
        Presentaremos temas que nos parezcan de interés sobre tecnología .NET, Procesos y Metodologías y todo aquello relacionado con el proceso de desarrollo de Software

        Month List

        BlogRoll

        Download OPML file OPML