tag:blogger.com,1999:blog-20830540991694795722024-03-13T19:27:37.290-07:00Just share my experienceRajiv Précieux Mounguenguehttp://www.blogger.com/profile/15481287992411150107noreply@blogger.comBlogger2125tag:blogger.com,1999:blog-2083054099169479572.post-72461868905470426112012-06-21T09:55:00.000-07:002012-06-25T04:58:41.299-07:00A WCF Sub/Pub Duplex ScenarioRecently, 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.<br><br> <h3><strong>Service Side</strong></h3>I try to make the Sub/Pub implemenation as generic as possible to be able to re-use it in others service.<br><br> <h4>Generic Implementation</h4> <p><strong>ISubscribeService</strong><br>Firstly, 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.<br>This is the interface definition: </p> <p><pre class="csharpcode"><span class="kwrd">using</span> System.ServiceModel;<br /><br />[ServiceContract]<br /><span class="kwrd">public</span> <span class="kwrd">interface</span> ISubscribeService<br />{<br /><span class="rem">/// <summary></span><br /><span class="rem">/// This method should be executed to subscribe to notifications from server.</span><br /><span class="rem">/// </summary></span><br />[OperationContract(IsOneWay = <span class="kwrd">true</span>)]<br /><span class="kwrd">void</span> SubscribeToNotifications(<span class="kwrd">string</span> clientId);<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// This method should be executed to unsubscribe to notifications from server.</span><br /><span class="rem">/// </summary></span><br />[OperationContract(IsOneWay = <span class="kwrd">true</span>)]<br /><span class="kwrd">void</span> UnsubscribeToNotifications(<span class="kwrd">string</span> clientId);<br />}<br /></pre><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><br /><strong>ServiceBase<T></strong><br>This is the generic class used to write the Sub/Pub mechanism for the service.<br><br><pre class="csharpcode"><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.ServiceModel;<br /><span class="kwrd">using</span> System.Timers;<br /><br /><span class="kwrd">public</span> <span class="kwrd">class</span> ServiceBase<T><br />{<br /><span class="preproc">#region</span> variables<br /><span class="preproc">#endregion</span><br /><br /><span class="preproc">#region</span> Constructors<br /><span class="kwrd">protected</span> ServiceBase()<br />{<br />SyncRoot = <span class="kwrd">new</span> Object();<br />Timer = <span class="kwrd">new</span> Timer();<br />}<br /><span class="preproc">#endregion</span><br /><br /><span class="preproc">#region</span> Properties<br /><span class="kwrd">protected</span> Object SyncRoot { get; <span class="kwrd">private</span> set; }<br /><span class="kwrd">protected</span> Timer Timer { get; <span class="kwrd">private</span> set; }<br /><span class="preproc">#endregion</span><br /><br /><span class="preproc">#region</span> methods<br /><span class="rem">/// <summary></span><br /><span class="rem">/// This method should be executed to subscribe to notifications from server.</span><br /><span class="rem">/// </summary></span><br /><span class="kwrd">protected</span> <span class="kwrd">void</span> SubscribeToNotifications(<span class="kwrd">string</span> clientId)<br />{<br /> var channel = OperationContext.Current.GetCallbackChannel<T>();<br /><br /><span class="rem">//Any message from a client we haven't seen before causes the new client to be added to our list </span><br /><span class="kwrd">lock</span> (SyncRoot)<br />{<br /><span class="kwrd">if</span> (SessionsController<T>.IsClientConnected(clientId))<br /><span class="kwrd">return</span>;<br /><br />SessionsController<T>.AddCallbackChannel(clientId, channel);<br />}<br />}<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// This method should be executed to unsubscribe to notifications from server.</span><br /><span class="rem">/// </summary></span><br /><span class="kwrd">protected</span> <span class="kwrd">void</span> UnsubscribeToNotifications(<span class="kwrd">string</span> clientId)<br />{<br /><span class="kwrd">lock</span> (SyncRoot)<br />{<br />SessionsController<T>.DeleteClient(clientId);<br />}<br />}<br /><span class="preproc">#endregion</span><br />}<br /></pre><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><br /><br><strong>SessionsController<T></strong><br>A geneic Class used to handle and manage the clients sessions for the service.<br><br><pre class="csharpcode"><span class="kwrd">using</span> System;<br /><span class="kwrd">using</span> System.Collections.Generic;<br /><span class="kwrd">using</span> System.Linq;<br /><br /><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> SessionsController<T><br />{<br /><span class="preproc">#region</span> Variables<br /><br /><span class="preproc">#endregion</span><br /><br /><span class="preproc">#region</span> Constructors<br /><span class="rem">/// <summary></span><br /><span class="rem">/// Class constructor.</span><br /><span class="rem">/// </summary></span><br /><span class="kwrd">static</span> SessionsController()<br />{<br />Clients = <span class="kwrd">new</span> Dictionary<<span class="kwrd">string</span>, T>();<br />}<br /><span class="preproc">#endregion</span><br /><br /><span class="preproc">#region</span> Properties<br /><span class="kwrd">public</span> <span class="kwrd">static</span> Dictionary<<span class="kwrd">string</span>, T> Clients { get; <span class="kwrd">private</span> set; }<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// Gets the total callback channels.</span><br /><span class="rem">/// </summary></span><br /><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">int</span> TotalCallbackChannels { get { <span class="kwrd">return</span> GetCallbackChannels().Count(); } }<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// Returns all available callback channels</span><br /><span class="rem">/// </summary></span><br /><span class="rem">/// <returns>Callback channels</returns></span><br /><span class="kwrd">public</span> <span class="kwrd">static</span> IEnumerable<T> AllCallbackChannels<br />{<br />get { <span class="kwrd">return</span> Clients.Select(c => c.Value); }<br />}<br /><span class="preproc">#endregion</span><br /><br /><span class="preproc">#region</span> Methods<br /><span class="rem">/// <summary></span><br /><span class="rem">/// Stores given client callback channel</span><br /><span class="rem">/// </summary></span><br /><span class="rem">/// <param name="clientId">Id of client's session</param></span><br /><span class="rem">/// <param name="callbackChannel">Callback channel for given client</param></span><br /><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> AddCallbackChannel(<span class="kwrd">string</span> clientId, T callbackChannel)<br />{<br /><span class="kwrd">if</span> (Clients != <span class="kwrd">null</span> && Clients.Count(c => c.Key == clientId) != 0)<br /><span class="kwrd">return</span>;<br /><br />var syncRoot = <span class="kwrd">new</span> Object();<br /><span class="kwrd">lock</span> (syncRoot)<br />{<br /><span class="kwrd">if</span> (Clients != <span class="kwrd">null</span> && Clients.All(c => c.Key != clientId))<br />{<br />Clients.Add(clientId, callbackChannel);<br />}<br />}<br />}<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// Checks whether given client is connected.</span><br /><span class="rem">/// </summary>s</span><br /><span class="rem">/// <param name="clientId">Id of client's session</param></span><br /><span class="rem">/// <returns>Whether client is connected</returns></span><br /><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> IsClientConnected(<span class="kwrd">string</span> clientId)<br />{<br /><span class="kwrd">return</span> Clients != <span class="kwrd">null</span> && Clients.Any(c => c.Key == clientId);<br />}<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// Returns all available callback channels except sender</span><br /><span class="rem">/// </summary></span><br /><span class="rem">/// <returns>Callback channels</returns></span><br /><span class="kwrd">public</span> <span class="kwrd">static</span> IEnumerable<T> GetCallbackChannels(<span class="kwrd">string</span> sessionId)<br />{<br />var filteredChannels = Clients.Where(channel => channel.Key != sessionId);<br /><br /><span class="kwrd">return</span> filteredChannels.Select(c => c.Value);<br />}<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// Returns callback channel for given client</span><br /><span class="rem">/// </summary></span><br /><span class="rem">/// <param name="clientId">Id of client's session</param></span><br /><span class="rem">/// <returns>Callback channel for given client</returns></span><br /><span class="kwrd">public</span> <span class="kwrd">static</span> T GetCallbackChannel(<span class="kwrd">string</span> clientId)<br />{<br /><span class="kwrd">return</span> Clients != <span class="kwrd">null</span> ? Clients.Single(c => c.Key == clientId).Value : <span class="kwrd">default</span>(T);<br />}<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// Returns all available callback channels</span><br /><span class="rem">/// </summary></span><br /><span class="rem">/// <returns>Callback channels</returns></span><br /><span class="kwrd">public</span> <span class="kwrd">static</span> IEnumerable<T> GetCallbackChannels()<br />{<br /><span class="kwrd">return</span> Clients.Select(c => c.Value);<br />}<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// Deletes callback channel for given client </span><br /><span class="rem">/// </summary></span><br /><span class="rem">/// <param name="clientId">Id of client's session</param></span><br /><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">void</span> DeleteClient(<span class="kwrd">string</span> clientId)<br />{<br /><span class="kwrd">if</span> (Clients == <span class="kwrd">null</span> || Clients.All(c => c.Key != clientId))<br /><span class="kwrd">return</span>;<br /><br />var syncRoot = <span class="kwrd">new</span> Object();<br /><span class="kwrd">lock</span> (syncRoot)<br />{<br /><span class="kwrd">if</span> (Clients.Any(c => c.Key == clientId))<br />{<br />Clients.Remove(clientId);<br />}<br />}<br />}<br /><span class="preproc">#endregion</span><br />}<br /></pre><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><br /></p><br /><h4>Use Case in an example service</h4>In my case, i used a service named StockService<br><br><pre class="csharpcode">[ServiceContract(CallbackContract = <span class="kwrd">typeof</span>(IClientCallBack))]<br /><span class="kwrd">public</span> <span class="kwrd">interface</span> IStockService : ISubscribeService <span class="rem">//The service interface inherit the interface defined early.</span><br />{<br /> <span class="rem">//You can define your Operations Contract</span><br />}<br /></pre><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><br /><br>i passed <strong>IClientCallBack</strong> as value for the CallbackContract property for the ServiceContract Attribute defined below: <br><br><pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">interface</span> IClientCallBack<br />{<br />[OperationContract(IsOneWay = <span class="kwrd">true</span>)]<br /> <span class="kwrd">void</span> SendProductsList(<span class="kwrd">string</span>[] list);<br />}<br /></pre><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><br /><br /><p>Once all those done, i describe the <strong>StockService</strong> implementation:</p><br /><p><pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> StockService : ServiceBase<IClientCallBack>, IStockService<br />{<br /><span class="preproc">#region</span> Notification<br /><span class="rem">/// <summary></span><br /><span class="rem">/// This method should be executed to subscribe to notifications from server.</span><br /><span class="rem">/// </summary></span><br /><span class="kwrd">void</span> ISubscribeService.SubscribeToNotifications(<span class="kwrd">string</span> clientId)<br />{<br />SubscribeToNotifications(clientId);<br />}<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// This method should be executed to unsubscribe to notifications from server.</span><br /><span class="rem">/// </summary></span><br /><span class="kwrd">void</span> ISubscribeService.UnsubscribeToNotifications(<span class="kwrd">string</span> clientId)<br />{<br />UnsubscribeToNotifications(clientId);<br />}<br /><span class="preproc">#endregion</span><br /><br /><span class="kwrd">public</span> StockService()<br />{<br />Timer.Elapsed += Process;<br />Timer.Interval = 2000;<br />Timer.Enabled = <span class="kwrd">true</span>;<br />Timer.Start();<br />}<br /><br /><span class="kwrd">private</span> <span class="kwrd">void</span> Process(<span class="kwrd">object</span> sender, EventArgs e)<br />{<br />var list = <span class="kwrd">new</span> List<<span class="kwrd">string</span>>();<br /><br /><span class="kwrd">for</span>(var i = 0; i <100; i++)<br />{<br />list.Add(<span class="str">"Item"</span> + i);<br />}<br /><br /><span class="kwrd">if</span> (SessionsController<IClientCallBack>.TotalCallbackChannels <= 0)<br /><span class="kwrd">return</span>;<br /><br /><span class="kwrd">lock</span>(SyncRoot)<br />{<br />var allChannels = SessionsController<IClientCallBack>.GetCallbackChannels();<br /><br /> allChannels.ToList().ForEach(c => c.SendProductsList(list.ToArray()));<br />}<br />}<br />}<br /><br /></pre><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><br />This is the ServiceModel configuration used in my web.config:<br><system.serviceModel><br><services><br><service behaviorConfiguration="StockServiceTypeBehavior" name="Stock.StockService"><br><endpoint address="" binding="wsDualHttpBinding" contract="Stock.IStockService"/><br></service><br></services><br><behaviors><br><serviceBehaviors><br><behavior name="StockServiceTypeBehavior"><br><!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --><br><serviceMetadata httpGetEnabled="true"/><br><!-- 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 --><br><serviceDebug includeExceptionDetailInFaults="true"/><br></behavior><br></serviceBehaviors><br></behaviors><br><serviceHostingEnvironment multipleSiteBindingsEnabled="true" /><br></system.serviceModel><br><br>After that, all it's done for the service. let's go to check out for the Client.<br></p><br /><h3>Client Side</h3><br /><p>I begin to define a CallbackController <br><pre class="csharpcode"><span class="kwrd">internal</span> <span class="kwrd">class</span> CallbackController : IStockServiceCallback<br />{<br /> <span class="kwrd">public</span> <span class="kwrd">void</span> SendProductsList(<span class="kwrd">string</span>[] list)<br />{<br /> MessageMediator.SendMessage(list, <span class="str">"Tag"</span>); <span class="rem">//You have to use a Message Mediator implementation</span><br />}</pre><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><br /></p><br /><p>I used a <a href="http://catel.codeplex.com/">Catel</a> ViewModel in my client:<br><pre class="csharpcode"><span class="rem">/// <summary></span><br /><span class="rem">/// MainWindow view model.</span><br /><span class="rem">/// </summary></span><br />[CallbackBehavior(UseSynchronizationContext = <span class="kwrd">false</span>)]<br /><span class="kwrd">public</span> <span class="kwrd">class</span> MainWindowViewModel : ViewModelBase<br />{<br /><span class="preproc">#region</span> Variables<br /><span class="kwrd">private</span> StockServiceClient Proxy { get; set; }<br /><span class="kwrd">private</span> <span class="kwrd">string</span> ClientId { get; set; }<br /><span class="kwrd">private</span> StockServiceClient Client { get; set; }<br /><span class="preproc">#endregion</span><br /><br /><span class="preproc">#region</span> Constructor & destructor<br /><span class="rem">/// <summary></span><br /><span class="rem">/// Initializes a new instance of the <see cref="MainWindowViewModel"/> class.</span><br /><span class="rem">/// </summary></span><br /><span class="kwrd">public</span> MainWindowViewModel()<br />{<br />MessageMediator .Register<<span class="kwrd">string</span>[]>(<span class="kwrd">this</span>,<br />(x) =><br />{ Liste = <span class="kwrd">new</span> ObservableCollection<<span class="kwrd">string</span>>(x); },<br /><span class="str">"Tag"</span>);<br />ClientId = Guid.NewGuid().ToString();<br />Client = <span class="kwrd">new</span> StockServiceClient(<span class="kwrd">new</span> InstanceContext(<span class="kwrd">new</span> CallbackController()));<br />Client.SubscribeToNotifications(ClientId); <br />}<br /><span class="preproc">#endregion</span><br /><br /><span class="preproc">#region</span> Properties<br /><span class="rem">/// <summary></span><br /><span class="rem">/// Gets the title of the view model.</span><br /><span class="rem">/// </summary></span><br /><span class="rem">/// <value>The title.</value></span><br /><span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> Title { get { <span class="kwrd">return</span> <span class="str">"View model title"</span>; } }<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// Gets or sets the property value.</span><br /><span class="rem">/// </summary></span><br /><span class="kwrd">public</span> ObservableCollection<<span class="kwrd">string</span>> Liste<br />{<br />get { <span class="kwrd">return</span> GetValue<ObservableCollection<<span class="kwrd">string</span>>>(ListeProperty); }<br />set { SetValue(ListeProperty, <span class="kwrd">value</span>); }<br />}<br /><br /><span class="rem">/// <summary></span><br /><span class="rem">/// Register the Liste property so it is known in the class.</span><br /><span class="rem">/// </summary></span><br /><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">readonly</span> PropertyData ListeProperty = RegisterProperty(<span class="str">"Liste"</span>, <span class="kwrd">typeof</span>(ObservableCollection<<span class="kwrd">string</span>>));<br /><span class="preproc">#endregion</span><br /><br /><span class="preproc">#region</span> Commands<br /><span class="rem">// TODO: Register commands with the vmcommand or vmcommandwithcanexecute codesnippets</span><br /><span class="preproc">#endregion</span><br /><br /><span class="preproc">#region</span> Methods<br /><br /><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> Close()<br />{<br />Client.UnsubscribeToNotifications(ClientId);<br />}<br /><br /><span class="preproc">#endregion</span><br />}</pre><br /><style type="text/css">.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }<br /></style><br /></p><br /><p>This is the ServiceModel configuration in my app.config:<br><system.serviceModel><br><bindings><br><wsDualHttpBinding><br><binding name="WSDualHttpBinding_IStockService" /><br></wsDualHttpBinding><br></bindings><br><client><br><br><endpoint address="http://localhost:807/StockService.svc" binding="wsDualHttpBinding"<br>bindingConfiguration="WSDualHttpBinding_IStockService" contract="Service.IStockService"<br>name="WSDualHttpBinding_IStockService"><br><identity><br><userPrincipalName value="Host\Rajiv" /><br></identity><br></endpoint><br></client><br></system.serviceModel><br><br>That's all.<br><br>I just hope that help someone (really sorry for the presentation, i will try to improve :)).<br>Waiting yours feedback. </p> Rajiv Précieux Mounguenguehttp://www.blogger.com/profile/15481287992411150107noreply@blogger.com0tag:blogger.com,1999:blog-2083054099169479572.post-67535107322717340542012-04-28T01:42:00.001-07:002012-04-28T01:51:28.816-07:00Just BloggedHi all, <br />
this is my first message on my brand new blog. Here i will try to share experience that i gain during solving different issue that I'm facing all days in my developer life.<br />
<br />
Warm regards.Rajiv Précieux Mounguenguehttp://www.blogger.com/profile/15481287992411150107noreply@blogger.com0Brazzaville, Congo-4.2666667 15.283333299999981-4.3905147 15.193210799999981 -4.1428187 15.373455799999981