A la hora de crear un cliente para un servicio
WCF
podemos hacer algo tan sencillo y rápido como botón derecho "Agregar referencia de Servicio" y aquí introducir la URL que contiene los meta-datos del servicio.
Visual Studio en este punto usa svcUtil para generar automáticamente las clases proxy y los tipos que se usarán en el servicio.
Hasta aquí todos estaremos de acuerdo que no hay modo más sencillo y rápido de generar un cliente que usando svcUtil. En caso que estemos trabajando en una arquitectura en la que disponemos de los tipos y la interfaz que se ha usado para crear el servicio, crear un "service reference" sería práctico pero poco óptimo dado que estaríamos generando clases y archivos que realmente no sería necesario crear en presentación (cliente).
Hoy veremos como usar la clase
ChannelFactory<T>
que nos permitirá generar un cliente para nuestro servicio. Para el ejemplo será necesario crear 3 proyectos; AreaTIC.Client (Consola), AreaTIC.Server (Consola) y AreaTIC.Shared (librería de clases).
Crearemos una solución que contenga los proyectos AreaTIC.Server y AreaTIC.Shared. En primer lugar crearemos los tipos que usaremos en las operaciones del servicio (
DataContract
). Para implementar el patrón estos tipos necesitaremos que sean accesibles tanto en servidor como cliente así que ubicaremos las clases en el proyecto AreaTIC.Shared en un namespace AreaTIC.Shared.DataContract.
namespace AreaTIC.Shared.DataContracts
{
[DataContract]
public class Tipo1
{
[DataMember]
public string Atributo1 { get; set; }
[DataMember]
public string Atributo2 { get; set; }
}
}
En segundo lugar, para crear un servicio
WCF
nos hará falta una interfaz con el atributo
[ServiceContract]
que contenga la firma de los métodos que se incluirán en el servicio. Dicha interfaz será necesaria tanto en servidor como cliente así que la ubicaremos dentro del proyecto AreaTIC.Shared en un namespace que llamaremos AreaTIC.Shared.ServiceContracts.
namespace AreaTIC.Shared.ServiceContracts
{
[ServiceContract]
public interface IServiceEjemplo
{
[OperationContract]
string FuncionEjemplo(Tipo1 pValue);
}
}
Crearemos la clase que implementará la interfaz anterior dentro de AreaTIC.Server.Services.
using AreaTIC.Shared.ServiceContracts;
using AreaTIC.Shared.DataContracts;
namespace AreaTIC.Server.Services
{
public class ServiceEjemplo:IServiceEjemplo
{
string IServiceEjemplo.FuncionEjemplo(Tipo1 pValue)
{
Thread.Sleep(5000);
//Implementación (...)
return "bla bla";
}
}
}
Para acabar con la parte servidor faltaría definir un
Binding
y hospedar el servicio (esta parte podría hacerse vía web.config
<system.servicemodel>
).
using System.ServiceModel;
using AreaTIC.Server.Services;
using AreaTIC.Shared.ServiceContracts;
namespace AreaTIC.Server
{
class Program
{
static void Main(string[] args)
{
try
{
Uri baseURI = new Uri("http://localhost:8080/Services/");
string Address = "EjemploAreaTIC";
ServiceHost hostEjemplo = new ServiceHost(typeof(ServiceEjemplo), baseURI);
string ContractTypeName="AreaTIC.Shared.ServiceContracts.IServiceEjemplo";
WSHttpBinding binding = new WSHttpBinding(SecurityMode.None);
hostEjemplo.AddServiceEndpoint(ContractTypeName, binding, Address);
Console.WriteLine("Servicio Ejemplo a la escucha");
}
catch (Exception)
{
Console.WriteLine("Error al hospedar el servicio");
}
finally
{
Console.ReadLine();
}
}
}
}
Llegado este punto ya tenemos el servicio a la escucha ahora veamos como generar el cliente usando
ChannelProxy
. En primer lugar crearemos otra solución que contenga un nuevo proyecto AreaTIC.Client al que añadiremos como referencia la librería de clases AreaTIC.Shared. En la misma clase Program.cs definiremos el
binding
,
endPointAddress
y conectaremos al servicio que hemos creado en el paso anterior mostrando la información que devuelve la llamada por pantalla.
using System.ServiceModel;
using AreaTIC.Shared.DataContracts;
using AreaTIC.Shared.ServiceContracts;
namespace AreaTIC.Client
{
class Program
{
static void Main(string[] args)
{
//definimos binding.
WSHttpBinding binding = new WSHttpBinding(SecurityMode.None);
//definimos endpoint
EndpointAddress endPoint = new EndpointAddress("http://localhost:8080/Services/EjemploAreaTIC");
//definimos factory y creamos canal.
ChannelFactory<IServiceEjemplo> factory = new ChannelFactory<IServiceEjemplo>(binding,endPoint);
//en este punto podríamos personalizar el comportamiento de nuestro cliente (serializador, inspectors, credenciales, certificados, ...);
factory.Open();
IServiceEjemplo wcfClient = factory.CreateChannel();
Console.WriteLine(wcfClient.FuncionEjemplo(new Tipo1()));
Console.ReadLine();
factory.Close();
}
}
}
Si todo ha ido bien, mostraremos el texto 'bla bla' por pantalla. En arquitecturas donde se accede a datos vía
WCF
es muy interesante usar
ChannelFactory<T>
en cliente para evitar tener una lista interminable de "Service Reference" que serán engorrosos de configurar vía app.config.
Hasta aquí el artículo de hoy. Espero les sea de ayuda y como siempre os animo a participar con vuestros comentarios y/o aportaciones. Recuerda que puedes seguir
areaTIC
en las redes sociales!