jeudi 21 juin 2012

Recently, i been faced a huge issue in working on a project. I was seeking to make a Sub/Pub mechanism using WCF that i succeed to do. But unfortunately, i was not get out the problem because i noticed an unexpected service behavior. I succeed to subscribe for the service notifications but after closed the client, others subscriptions didn't work. After solved the issue, i decided to share it with community. There is the approach i used.

Service Side

I try to make the Sub/Pub implemenation as generic as possible to be able to re-use it in others service.

Generic Implementation

ISubscribeServiceFirstly, i begin to define a ISubscribeService Interface wich will allow me after to have an implementation Class to make subscription on the service for the notifications.This is the interface definition:

using System.ServiceModel;

[ServiceContract]publicinterface ISubscribeService{/// <summary>/// This method should be executed to subscribe to notifications from server./// </summary>[OperationContract(IsOneWay = true)]void SubscribeToNotifications(string clientId);

/// <summary>/// This method should be executed to unsubscribe to notifications from server./// </summary>[OperationContract(IsOneWay = true)]void UnsubscribeToNotifications(string clientId);}

ServiceBase<T>This is the generic class used to write the Sub/Pub mechanism for the service.

//Any message from a client we haven't seen before causes the new client to be added to our list lock (SyncRoot){if (SessionsController<T>.IsClientConnected(clientId))return;

SessionsController<T>.AddCallbackChannel(clientId, channel);}}

/// <summary>/// This method should be executed to unsubscribe to notifications from server./// </summary>protectedvoid UnsubscribeToNotifications(string clientId){lock (SyncRoot){SessionsController<T>.DeleteClient(clientId);}}#endregion}

SessionsController<T>A geneic Class used to handle and manage the clients sessions for the service.

/// <summary>/// This method should be executed to unsubscribe to notifications from server./// </summary>void ISubscribeService.UnsubscribeToNotifications(string clientId){UnsubscribeToNotifications(clientId);}#endregion

This is the ServiceModel configuration used in my web.config:<system.serviceModel><services><service behaviorConfiguration="StockServiceTypeBehavior" name="Stock.StockService"><endpoint address="" binding="wsDualHttpBinding" contract="Stock.IStockService"/></service></services><behaviors><serviceBehaviors><behavior name="StockServiceTypeBehavior"><!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --><serviceMetadata httpGetEnabled="true"/><!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --><serviceDebug includeExceptionDetailInFaults="true"/></behavior></serviceBehaviors></behaviors><serviceHostingEnvironment multipleSiteBindingsEnabled="true" /></system.serviceModel>

After that, all it's done for the service. let's go to check out for the Client.

/// <summary>/// Register the Liste property so it is known in the class./// </summary>publicstaticreadonly PropertyData ListeProperty = RegisterProperty("Liste", typeof(ObservableCollection<string>));#endregion