Creación de un chat WCF
En este artículo trataremos de configurar WCF para que mantenga una comunicación bidireccional mediante la creación de un chat muy simple.
WCF
Windows Communication Foundation o WCF, es la plataforma de mensajería que forma parte del framework .NET desde la versión 3.0
WCF es un marco de desarrollo para crear aplicaciones orientadas a servicios que permite comunicación bidireccional (Duplex), WCF está bien documentado tanto por Microsoft ®, como por la cantidad de artículos y tutoriales disponibles en la red.
Un servicio WCF, es expuesto a sus clientes a través de un endpoint, este presenta las siguientes características:
- Dirección de acceso al endpoint, en este caso utilizaremos http://localhost:5000/
- Tipo de enlace, será WSDualHttpBinding
- Contrato de servicio, definiremos IChatService como contrato de servicio.
Estructura de la aplicación
- Crearemos dos proyectos
- Un servidor que expondrá un contrato de servicio con un tipo de enlace bidireccional ( wcf duplex)
- Un cliente que lo consumirá
El contrato de servicio
Desde Visual Studio, crearemos una aplicación de tipo WinForms, WCF_Server
Creamos una carpeta WCFService y sobre esta con el botón derecho, agregar nuevo elemento, le agregamos un servicio WCF al que llamaremos ChatService
Como vemos, visual studio ha creado dos archivos ChatService que implementa IChatService, esta interfaz es la que sirve como contrato del servicio.
Podemos entender que un contrato de servicio son unas reglas o restricciones impuestas por el servidor de forma que le dice al cliente a que métodos puede acceder, y con qué sintaxis, que parámetros necesitan esos métodos, que devuelven,…
Modificamos IChatService agregando, una contrato de callback en la definición del contrato este será el referenciado en la parte de comunicación Servidor -> Cliente
IChatService
[ServiceContract(CallbackContract = typeof(IChatServiceCallback), SessionMode = SessionMode.Allowed)] public interface IChatService { [OperationContract] void SendMessage(ChatMessage msg); }
Contrato de callback (IChatServiceCallback) Servidor -> Cliente
public interface IChatServiceCallback { [OperationContract(IsOneWay = true)] void MessageReceived(ChatMessage msg); }
Como vemos IChatService lleva un método que tiene como parámetro un objeto del tipo ChatMessage, creémoslo.
Agregamos una carpeta model, y en esta carpeta le agregamos una clase muy simple, a modo de modelo del mensaje del chat, quien envía y que mensaje.
ChatMessage
[DataContract] public class ChatMessage { [DataMember] public string Sender { get; set; }
[DataMember] public string Message { get; set; } }
Esta clase debe estar correctamente decorada para que WCF pueda serializarla, le agregamos los atributos DataContract y DataMember. Para que compile correctamente la librería debe referenciar las dlls System.Runtime.Serialization y System.ServiceModel.
Si arrancásemos ahora el servidor, nos daría una excepción
System.InvalidOperationException: ‘El contrato requiere Duplex, pero el enlace ‘BasicHttpBinding’ no lo admite o no está configurado correctamente para admitirlo.’
Esta viene de haber agregado el contrato de callback convirtiendo el binding en uno de tipo duoplex, debemos sustituir en el archivo de configuración basicHttpBinding por wsDualHttpBinding
<endpoint address="" binding="wsDualHttpBinding" contract="WCF_Server.WCFService.IChatService"> <identity> <dns value="localhost" /> </identity> </endpoint>
Arrancaremos la aplicación y nos desasociamos de esta, necesitaremos levantar el servidor para poder referenciarlo a continuación
Para desasociamos de la depuración, es decir, dejamos de utilizar el contexto de depuración pero permitimos que la aplicación siga corriendo, para ello desde la opción de menú/depurar hacemos click en desasociar todo.
Cliente WCF
Ahora crearemos un cliente en Winforms, al que llamaremos WCFClient
Al formulario principal le agregaremos un textbox donde poner el nombre, otro con el mensaje, un botón de enviar mensaje y un editor donde visualizar el chat.
Le agregamos una referencia de servicio con la url en la que está levantado el servidor
Crearemos una clase (ChatServiceCallback) que reciba los eventos de callback implementando IChatServiceCallback
[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple)] internal class ChatServiceCallback : IChatServiceCallback { public event EventHandler OnMessageReceived;
public void MessageReceived(ChatMessage msg) { OnMessageReceived.Invoke(this, new ChatEventArgs(msg)); } }
Esta implementación vemos que tiene un evento OnMessageReceived, que se dispara cuando se recibe el callback (MessageReceived) desde el servidor, nos podemos subscribir a él.
callbackManager.OnMessageReceived += CallbackManager_OnMessageReceived;
Inicializaremos el acceso al servidor cliente a través de la referencia expuesta
indicando cual es la implementación de IChatServiceCallback
private void InitializeClient() { callbackManager = new ChatServiceCallback(); callbackManager.OnMessageReceived += CallbackManager_OnMessageReceived; server = new ChatServiceClient(new InstanceContext(callbackManager)); }
Por último arrancaremos la aplicación seleccionando la opción de arranque múltiple (Botón derecho sobre la solución -> seleccionar proyectos de inicio).
Lanzaremos adicionalmente otro cliente y probaremos que todo vaya bien
Resultado
No ha quedado un chat funcional, pero sirve como prueba conceptual de la comunicación bidireccional entre un servidor y un cliente WCF.
Buen artículo wcf sigue siendo el mejor framework de comunicación en. NET