Friday, July 24, 2009

Pub/sub sample using HTTP polling duplex WCF channel in Microsoft Silverlight 3

NOTE: Many people reading this post are really looking for a publish\subscribe solution for Silverlight to implement a web chat or a stock quote application for the browser, a multiplayer online game, or some form of a web based collaboration tool, among others. If that fits your profile, you may want to check out http://laharsub.codeplex.com. Laharsub is an open source pub\sub message server for web clients, including Silverlight. It aspires to address the needs of people like you, who are interested in the subject matter of this post as well as willing to contribute your scenarios and requirements by leaving a comment. Enjoy!

This sample demonstrates how a Microsoft Silverlight 3 application can consume asynchronous data notifications from the server using the polling duplex protocol of Windows Communication Foundation (WCF). I am also discussing selected aspects of the implementation, in particular related to performance. The full source code and Visual Studio solution of the sample is available for download. Please also check the Silverlight development environment prerequisites.

The application follows a publisher/subscriber architecture and consists of three components:

  • PubSubService.svc is a WCF web service that manages client subscriptions to topics and sending asynchronous notifications to clients when data is published to the topic they are subscribed to. The service exposes an endpoint with a binding based on the polling duplex protocol. The server side implementation of the protocol is available through the PollingDuplexHttpBinding class in the System.ServiceModel.PollingDuplex.dll .NET Framework 3.5 library shipped as part of Microsoft Silverlight 3 SDK.  
  • PubSubClient.aspx is an ASP.NET page that contains a Microsoft Silverlight 3 client application that can act as both a subscriber and a publisher. The application allows the user to subscribe to notifications related to a particular topic as well as publish data to that topic. The client communicates with the PubSubService.svc service using a WCF proxy and the client side implementation of the PollingDuplexHttpBinding, which ships as a Silverlight 3 extension assembly System.ServiceModel.PollingDuplex.dll within the Microsoft Silverlight 3 SDK.
  • PublisherClient.aspx is an ASP.NET page that contains a Microsoft Silverlight 3 client application that can act as a publisher only. The application allows the user to start publishing data to a particular topic at specified frequency, therefore causing a stream of regular notifications to be sent to subscribed clients. The client communicates with the backend PubSubService.svc using the same mechanism as PubSubClient.aspx.

There are two key scenario types that can be demonstrated using this sample: collaboration and broadcast.

Collaboration Scenario

In the collaboration scenario we have a small set of clients (typically 2) acting as both publishers and subscribers of the same topic. An example of a collaboration scenario is a chat. In order to simulate the collaboration scenario, open the PubSubClient.aspx client application in two or more browser windows, subscribe to the same topic in each of them, and then start publishing to the topic by typing text in the provided text box in any of the clients. You should observe the text being propagated through notifications to all other clients. 

Broadcast Scenario

In the broadcast scenario we have multiple clients subscribed to the same topic, and a small number of publishers (typically 1) publishing to the topic. An example of a broadcast scenario is propagating stock quotes from a single source to multiple client applications. In order to simulate the broadcast scenario, open the PubSubClient.aspx client application in multiple browser windows and subscribe to the same topic. Then open the PublisherClient.aspx client application in a single browser window and start publishing to the same topic you have subscribed to. You should observe periodic notifications arriving at all subscribed clients.

Key implementation aspects

Server

The PubSubService.svc encapsulates the pub/sub server logic. It is a WCF duplex service exposed over the PollingDuplexHttpBinding that shipped with Microsoft Silverlight 3. The binding implements a comet-style long polling protocol which enables firewall traversal by leveraging HTTP protocol to enable duplex communication.

A few implementation aspects of the service are worth calling out given their implications for performance of the service.

In the broadcast scenario or a collaboration scenario that involves more than 2 participants, identical messages are often sent to several clients. Given that a substantial portion of the cost of sending a message is related to serializing its content, it is worthwhile to pre-serialize a message once and then send a copy of it multiple times. In order to accomplish this, the callback contract of a pub/sub service should take a Message as a parameter as opposed to typed parameters. This allows the message to be pre-serialized and converted to a MessageBuffer using TypedMessageConverter. Then, for every notification to be sent, the MessageBuffer can be used to create a clone of the Message without incurring the serialization cost. This is how the WCF service contract of the pub/sub service looks like:

[ServiceContract(CallbackContract = typeof(INotification))]
public interface IPubSub
{
    [OperationContract(IsOneWay = true)]
    void Subscribe(string topic);

    [OperationContract(IsOneWay = true)]
    void Publish(string topic, string content);
}

[ServiceContract]
public interface INotification
{
    [OperationContract(IsOneWay = true,
                                AsyncPattern = true, Action="*")]
    IAsyncResult BeginNotify(Message message,
                                       AsyncCallback callback, object state);
    void EndNotify(IAsyncResult result);
}

[MessageContract]
public class NotificationData
{
    public const string NotificationAction = "http://…";

    [MessageBodyMember]
    public string Content { get; set; }
}

When a notification is to be sent to multiple clients over the INotification service contract, the message is first pre-serialized using a TypedMessageConverter:

TypedMessageConverter messageConverter = 
    TypedMessageConverter.Create(
        typeof(NotificationData),
        NotificationData.NotificationAction,
        "http://…");

Message notificationMessage = messageConverter.ToMessage(
    new NotificationData { Content = “hello” });
MessageBuffer notificationMessageBuffer =
    notificationMessage.CreateBufferedCopy(65536);

Then a copy of the message is sent to all clients, thus avoiding the serialization cost on every send:

foreach (INotification callbackChannel in clientsToNotify)
{
    try
    {
        callbackChannel.BeginNotify(
            notificationMessageBuffer.CreateMessage(), 
            onNotifyCompleted, callbackChannel);
    }
    catch (CommunicationException) { }
}

Another aspect to emphasize in how the notifications are sent is related to the use of asynchronous API INotification.BeginNotify/EndNotify. Sending a large number of notifications is a high latency activity. Using asynchronous APIs to do so results in more efficient use of system resources compared to the use of synchronous APIs. Alternatively, synchronous APIs could be used if each of the notifications was scheduled to be sent on a separate worker thread from the thread pool. Measurements of both methods indicate the performance difference between them is negligible.

Finally, the concurrency mode of the WCF service is set to ConcurrencyMode.Multiple, and instance mode to InstanceMode.Single. This requires explicit synchronization code to be added around access to critical resources (i.e. data structures related to subscriptions), but the extra effort pays off in reduced contention of concurrent requests to the service:

[ServiceBehavior(
    ConcurrencyMode = ConcurrencyMode.Multiple, 
    InstanceContextMode = InstanceContextMode.Single)]
public class PubSubService : IPubSub
{
    // …       
}

There are several more performance considerations for setting up a pub/sub service based on the HTTP polling duplex protocol. I will cover them in an upcoming post dedicated to performance tuning of such scenario.

Client

The key implementation aspect of the pub/sub service client in the sample is the use of the Add Service Reference feature of Visual Studio to automatically generate a proxy to such a service. This is a major usability improvement from Silverlight 2 to Silverlight 3. After the proxy has been added to the client project using the Add Service Reference feature of Visual Studio (or the slsvcutil.exe command line tool offering corresponding functionality), consuming asynchronous notifications from the sever is as easy as hooking up events on the generated proxy:

PubSubClient client = new PubSubClient(
    new PollingDuplexHttpBinding(),
    new EndpointAddress(“http://…”));
this.client.NotifyReceived +=
    new EventHandler<NotifyReceivedEventArgs>(NotifyReceived);
this.client.SubscribeAsync(“my topic”);

Thanks to this feature, the entire pub/sub client application is around 100 lines of C# code.

128 comments:

  1. All I get is: ERROR: The remote server returned an error: NotFound.
    What's that mean?

    ReplyDelete
  2. It's not performance I care about so much. I need a *scalable* server. Do you have any metrics related to this?

    ReplyDelete
  3. Hi,

    About the NotFound error: there is missing a DLL: "The referenced component 'System.ServiceModel.PollingDuplex' could not be found." in the Asp.net project.

    Thanks,

    Vítor

    ReplyDelete
  4. Looking at the code, it uses a session-ful binding, a singleton instance and in-memory state - all this means that scaling it out in a server farm is kind of tedious.

    What we really need is an enterprise/web-class pub/sub solution for SL and WCF.

    Any comment on this?

    Thanks.

    ReplyDelete
  5. I get this error: ERROR: The remote server returned an error: NotFound.
    and I am not missing the .dll mentioned above.

    ReplyDelete
  6. Current implementation of the HTTP long polling in WCF requires sessionful WCF channels and therefore affinity to a specific backend for the lifetime of a single polling duplex session. If your load balancer cannot support such scenario (which requires content based routing), you will not be able to achieve scale-out of the service in a way that is completely transparent to the client. One possible mitigation of this problem is to have the client explicitly select the backend to communicate with based on configuration, data dynamically obtained from a backend, or a heuristic (e.g. the hash value of the "topic" the client wants to subscribe to).

    ReplyDelete
  7. Bydia, regarding the NotFound error, one thing to check is whether the PubSubService.svc is properly published and accessible. I suggest you set it as a start page in your project and check if the WCF service help page shows up in your browser when you start the solution.

    ReplyDelete
  8. If I run the .svc file directly in browser I get: The type 'System.ServiceModel.Configuration.PollingDuplexElement, System.ServiceModel.PollingDuplex' registered for extension 'pollingDuplex' could not be loaded
    With this line in red: pollingDuplex maxPendingSessions="2147483647"

    ReplyDelete
  9. Found the problem. The install of v3 tools didn't remove the old install and the new install didn't register the pollingDuplex dll as global... so it was looking at the old dll. All compiled well and no errors... except at runtime.

    ReplyDelete
  10. I have the same problem as bydia. The assembly was not in the cache, so I installed it with gacutil from C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Libraries\Server\.

    It's now in the assembly cache with a public key token of 31bf386ad364e35, V3.0.0.0.

    Starting the .svc file reports the same error as above.

    Thoughts? :-)

    Thanks!

    ReplyDelete
  11. Ok, I'm working now. I had to remove and re-add the reference copylocal to true.

    Thanks!

    ReplyDelete
  12. theStarsMyDesitination, one does not need to GAC the System.ServiceModel.PollingDuplex assembly for the scenario to work. Once the assembly is deployed into the bin folder of the application, the service can expose an endpoint over the polling duplex binding. This also works fine in partial trust environment (offered in shared hosting situations).

    ReplyDelete
  13. I've been struggling with this sample solution for a while now, and could use some help. After downloading the sample solution, fixing the System.ServiceModel.PollingDuplex reference issue, everything is fine. I'm able to use 2 independent clients to publish / subscribe messages back and forth - life is good. However, if I simply navigate to the Silverlight PubSub client project, choose "Update Service Reference..." from within VS2008, all of the DuplexClientBase<> information in the proxy class is lost, and the proxy reverts back to a standard request/reply client (this also obviously breaks the project). Any ideas on what would be causing this behavior? I've manually looked at the WSDL, for the project on my machine _before_ updated the service reference, and it looks like the WSDL is missing all information required to convey the fact that this is a duplex service.

    I'm using VS2008SP1, Silverlight 3 SKD / tools (and yes, Silverlight 2 is _completely_ uninstalled) on Vista Utlimate x64, and running the solutions using Cassini.

    ReplyDelete
  14. This is a bug in the sample, thank you for reporting it. I posted an updated version of the sample with a fix at http://janczuk.org/code/samples/PollingDuplexSample.zip.
    The bug in the sample was related to a wildcard action on the INotification.Notify operation contract. This was preventing the WSDL generation logic to generate WSDL for the duplex contract, hence preventing the Update Service Reference in Visual Studio from completing its job. The fix was to specify the actual action used to send the notification to the client.

    ReplyDelete
  15. Thank you for the great sample code. I am trying to implement multiple call back contracts on the server side, so that the client can be notified about different events. The service contract will remain the same (Subscribe/Publish) but the callback contract needs to be extended in addition to "BeginNotify" method. I was not able to implement this successfully. The client would get an exception "channel was aborted" and no data would be received. It seems that only one callback channel can be implemented. What am I doing wrong? thank you.

    ReplyDelete
  16. There is a few things that need to happen I can think of to enable diffrent types of notifications: 1) add new service operations to INotification contract; make sure they use different action names, 2) add message contracts similar to NotificationData corresponding to the different notification types, 3) add new types of TypedMessageConverter for all those new message contracts to enable sending pre-serialized messages; make sure that a TypedMessageConverter for a given notification type uses the message action as the corresponding service operation on INotification interface, 4) don't forget to run Update Service Reference on the service reference in the PubSubClient.

    ReplyDelete
  17. Thank you very very much for the quick response. I've been strugling with this for two days now. I had everything implemented except the different actions. It is working great now. I am curious, however, on how this works behind the scenes, especially the action parameter in the [OperationContract] attribute. Again, thank you very much for your help.

    ReplyDelete
  18. The OperationContractAttribute.Action controls the WS-Addressing Action that will be generated on the message. This value allows the client to demultiplex incoming server notifications to the appropriate event handler on the client proxy.

    ReplyDelete
  19. Hi! I can build it, add one more service and run it by using Visual Studio Development Server, there is no error occured.. But when I tried to run it using my localhost.. There is an error "The remote server returned an error: Not Found", can you help me? (I run PubSubService.svc on my localhost finely)
    Thanks in advance
    Duc To

    ReplyDelete
  20. Duc To, is it the browser reporting the error because you cannot reach the *.aspx file, or is it is the Silverlight application reporting the error after the browser has finished loading the *.aspx file?

    ReplyDelete
  21. The aspx file is loaded ok, but when I press subscribe button, there is notification: "ERROR: The remote server returned an error: NotFound". It is really weird as I try to browse the svc file and it is loaded normally.. I am using IIS v.5.1. Do I have to modify anything to let it run with IIS, instead of development server?
    Thanks

    ReplyDelete
  22. I found the reason why. In development server, it does not include project name so your format "http://" + ... + "/PubSubService.svc" is fine.. But when i switch it to localhost, the correct becomes "http://" + ... + "/PubSubService/PubSubService.svc" How fool I am.. I kept thinking on my mind that the issue is on web config or ISS configuration files side and do not look at the code lines..
    Thanks for the sample, Tomasz.. It is great!
    Duc To

    ReplyDelete
  23. If you get the 'System.ServiceModel.Configuration.PollingDuplexElement, System.ServiceModel.PollingDuplex' registered for extension 'pollingDuplex' could not be loaded error then your web project is referencing the silverlight 2 version of the polling dll. remove it and add the silverlight 3 version.

    ReplyDelete
  24. Hi

    How could one have a windows application as a publisher?

    Thanks
    Q

    ReplyDelete
  25. PollingDuplexHttpBinding is not currently available as a client side component for .NET Framework. Please note that having a client that publishes notifications does not require duplex capability - it can be built as a separate request/response WCF service end exposed over a simple binding like BasicHttpBinding. For windows application clients that need to receive asynchronous notifiations over duplex contracts, consider using WsDualHttpBinding or NetTcpBinding, both of which offer duplex communication.

    ReplyDelete
  26. Thank you for sharing. Very useful exmaple.

    ReplyDelete
  27. "Please note that having a client that published notifications does not require duplex capability" Can you tell us more clearly, a hint or an example.. I want to publish notification from asp.net code behind but do not know how to do it
    Thanks in advance
    Duc To

    ReplyDelete
  28. Publishing a notification is achieved by sending multiple messages using callback channels of connected clients. It is up to the server's code to decide how the message to be published is generated: it can have been sent to the server from outside (this is what I was referring to as a "client that publishes notifications"), or the server could have generated it using mechanisms of its own. In scenarios where the content to be published is sent to the server by one of the clients (which is exactly what the sample demonstrates), it does not need to happen over the polling duplex protocol. A client could call a method on a WCF service exposed over BasicHttpBinding that accepts the content to be published, and as a result of that method invocation the WCF service could initatie sending notifications to clients that connected using the polling duplex binding. The fact that the sample reuses an existing connection to the server based on the polling duplex binding to send publish messages is an implementation detail.

    ReplyDelete
  29. I tried to call a method on a WCF service over basicHttpBinding but getting messages "Contract requires Duplex, but Binding "WsHttpBinding" doens't support it or isnt configured properly to support it :( Do you know why?

    ReplyDelete
  30. You will need to create a second WCF service with a simplex contract (e.g. one Publish method) and expose it over BasicHttpBinding. The IPubSub service contract in the sample is indeed a duplex contract and cannot be exposed over bindings that do not support duplex communication.

    ReplyDelete
  31. Could you post SL3 code which doesn't use proxy generation and uses the Channel Model instead?
    (All existing samples, including MSDN ones no longer work after migrating to SL3)

    Thanks.
    Alex Mikunov

    ReplyDelete
  32. Alex, this pub\sub sample has been created with SL3, there should be no need to migrate it over. Can you explain the problem you are experiencing?

    ReplyDelete
  33. You have used Add Service/Proxy generation to create a SL 3 client code for your duplex example (look in your PollingDuplexSample\PubSubClient\Service References and PollingDuplexSample\PublisherClient\Service References\Proxy folders).
    But if you do it via use of the Channel Model (a direct method, w/o proxy generation) then you will encounter a problem -- it simply doesn't work

    More on use of Channel Model, etc. check this link on MSDN:
    "How to: Access a Duplex Service with the Channel Model"

    Alex Mikunov

    ReplyDelete
  34. Alex,

    you can write an SL3 pub\sub client using channel model directly, it is just more work and code than an approach that uses proxy generation. This is because you have to use the more involved IAsyncResult-based async model, as well as handle notifications arriving on a non-UI thread.

    First you need to manually declare the duplex contract, making sure the operations originating from the client (Subscribe and Publish) are asynchronous:

    [ServiceContract]
    public interface INotification
    {
    [OperationContract(IsOneWay = true, Action = NotificationData.NotificationAction)]
    void Notify(Message message);
    }

    [ServiceContract(CallbackContract = typeof(INotification))]
    public interface IPubSub
    {
    [OperationContract(IsOneWay = true, AsyncPattern = true)]
    IAsyncResult BeginSubscribe(string topic, AsyncCallback callback, object state);
    void EndSubscribe(IAsyncResult result);

    [OperationContract(IsOneWay = true, AsyncPattern = true)]
    IAsyncResult BeginPublish(string topic, string content, AsyncCallback callback, object state);
    void EndPublish(IAsyncResult result);
    }

    Next you need to implement the INotification interface on the client side. The main user control is a convenient location:

    public partial class MainPage : UserControl, INotification

    //...

    public void Notify(Message notification)
    {
    this.AddNotification("SERVER NOTIFICATION: " + notification.GetBody<NotificationData>().Content);
    }

    Then, instead of instantiating the generated proxy, you need to use DuplexChannelFactory<T> directly to create a proxy instance and call the asynchronous Subscribe method:

    DuplexChannelFactory<IPubSub> factory = new DuplexChannelFactory<IPubSub>(
    new InstanceContext(this),
    new PollingDuplexHttpBinding { UseTextEncoding = true },
    new EndpointAddress(new Uri(App.Current.Host.Source + "/../../PubSubService.svc")));
    this.client = factory.CreateChannel();
    this.client.BeginSubscribe(this.TopicName.Text, new AsyncCallback(this.OnSubscribed), null);

    Similarly, you are using the IAsyncResult based async model to call Publish from the client:

    this.client.BeginPublish(this.TopicName.Text, this.PublishText.Text,
    new AsyncCallback(this.OnPublished), this.PublishText.Text);

    Lastly, you need to implement the OnSubscribed and OnPublished callbacks and process any errors:

    void OnSubscribed(IAsyncResult result)
    {
    try
    {
    this.client.EndSubscribe(result);
    }
    catch (Exception e)
    {
    this.OnError(e);
    }
    }

    void OnPublished(IAsyncResult result)
    {
    try
    {
    this.client.EndPublish(result);
    }
    catch (Exception e)
    {
    this.OnError(e);
    }
    this.Dispatcher.BeginInvoke(delegate
    {
    this.AddNotification("CLIENT ACTION: Published to topic " + this.TopicName.Text + ": " + result.AsyncState);
    });
    }

    void OnError(Exception e)
    {
    lock (this.syncRoot)
    {
    ((IClientChannel)this.client).Close();
    this.client = null;
    }
    this.Dispatcher.BeginInvoke(delegate
    {
    this.AddNotification("ERROR: " + e.Message);
    this.TopicName.IsEnabled = this.SubscribeButton.IsEnabled = true;
    this.PublishText.IsEnabled = false;
    });
    }

    As you can see, this pattern is more involved that the event-based async model offered by the generated proxy.

    ReplyDelete
  35. Thank you for the response

    Thanks.
    Alex

    ReplyDelete
  36. I am pulling My hair out.

    Through the process of Getting my application working, I have experienced many of the issues where the Service is invalid, such as"The type 'System.ServiceModel.Configuration.PollingDuplexElement, System.ServiceModel.PollingDuplex' registered for extension 'pollingDuplex' could not be loaded.
    "

    which is where I am at now. All of the answers here were helpful to me at avrious points and I got everything working.

    At Some point when I went to update one of my service references because I made a Namespace change ( to remove the samples namespaces and bring things in line with our naming convetions)

    So I try Bringing up my service in IE and I get the above error still. I don't know what is wrong or how I caused this to come back.

    I have the following in my Web.config:


    {system serviceModel}
    {extensions}
    {bindingElementExtensions}
    {add name="pollingDuplex" type="System.ServiceModel.Configuration.PollingDuplexElement, System.ServiceModel.PollingDuplex"/}
    {/bindingElementExtensions}
    {/extensions}
    {behaviors}
    {serviceBehaviors}
    {behavior name="PubSubServicesBehavior"}
    {serviceMetadata httpGetEnabled="true"/}
    {serviceDebug includeExceptionDetailInFaults="true"/}
    {serviceThrottling maxConcurrentSessions="2147483647"/}
    {/behavior}
    {/serviceBehaviors}
    {/behaviors}
    {bindings}
    {customBinding}
    {binding name="pollingDuplexBinding"}
    {binaryMessageEncoding/}
    {pollingDuplex maxPendingSessions="2147483647" maxPendingMessagesPerSession="2147483647" inactivityTimeout="02:00:00" serverPollTimeout="00:05:00"/}
    {httpTransport/}
    {/binding}
    {/customBinding}
    {/bindings}
    {services}
    {service behaviorConfiguration="PubSubServicesBehavior" name="Redacted"}
    {endpoint address="Redacted.com" binding="pollingDuplex" contract="Redacted.Interfaces.ISub"/}
    {endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/}
    {/service}
    {service behaviorConfiguration="PubSubServicesBehavior" name="Redacted"}
    {endpoint address="Redacted.com" binding="basicHttpBinding" contract="Redacted.Interfaces.IPub"/}
    {endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/}
    {/service}
    {/services}
    {/system serviceModel}

    I split the service in half, so I can publish from a Windows Mobile Device and Subscribe from a Silverlight client hosted inside an aspx page, and had everything working.

    Now I have the System.ServiceModel.PollingDuplex.dll File, the 3.0.0.0 Server Version referenced into my web project. It is not installed in my GAC, though I have also tried this.

    I don't know what is wrong, can you point me in the right direction?

    One of the weird things is that the SubService Works, and thats the One that uses Polling Duplex, but the PubService Gives the Errors about PollingDuplex but it uses basicHttpBinding!

    Also, the {BindingDuplex} Sub element under custom binding is highlighted in blue and if I ouse over it says "the Element 'binding' has invalid child element 'pollingDuplex' List of elements expected........"

    I have always had this error showing even when my project worked.

    ReplyDelete
  37. sdevlin,

    one typical situation when one would get this error is when the server side System.ServiceModel.PollingDuplex.dll is not located in the bin subdirectly of the vroot where your web application is deployed. (The dll does not need to be GACed as you noted). Make sure the "Copy local" property of this DLL under References in your project is set to "True".

    I undertand you have two *.svc files in your project right now. Are you able to access them directly from your browser? If not, what error do you get?

    The blue line under the pollingDuplex element in your config indicates the configuration schema file installed in VS does not recognie the element. This is OK, since this is a config extension explicitly registered in your config file.

    ReplyDelete
  38. Copy Local is not an option in Web Project. I successfully set that property when I was working on the sample, but its just not there in a web project.

    My error is :

    Configuration binding extension 'system.serviceModel/bindings/pollingDuplex' could not be found. Verify that this binding extension is properly registered in system.serviceModel/extensions/bindingExtensions and that it is spelled correctly.

    I have the File Referenced and it is Auto Update.

    I have done this add remove of the ref many times. I don't know why but sometimes it adds:

    {add assembly="System.ServiceModel.PollingDuplex, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf386ad364e35"/}

    to {Compilations}{Assemblies}

    and sometimes not. I think when I have referenced it when it was in the gac it adds that line, but if I ref a location otherwise, then not. I am currently trying to reference a local path ( in my TFS tree). So I added that line manually and I get:

    Could not load file or assembly 'System.ServiceModel.PollingDuplex\, Version\=3.0.0.0\, Culture\=neutral\, PublicKeyToken\=31bf386ad364e35' or one of its dependencies. The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)

    which I now assume is because when you add that line it is looking in the gac, but I don't have it loaded in the gac.


    I feel like I am running in circles.

    ReplyDelete
  39. sdevlin,

    If your WCF service is part of a web site (as opposed to a web application), you will need to manually add a "bin" folder to the web site project and copy System.ServiceModel.PollingDuplex.dll to that directory. The config loader will then able to find the assembly referenced in the WCF extensions section of the web.config file.

    ReplyDelete
  40. I have a Bin Folder, and It COntains System.ServiceModel.PollingDuplex.DLL

    ReplyDelete
  41. Can you confim this is the correct System.ServiceModel.PollingDuplex.dll? The SL3 SDK contains two: one is a client side for SL3, adn the other is server side for .NET 3.5. You need the server side one in the bin folder.

    ReplyDelete
  42. Tomasz, thank you for your help on this. I disappeared for a few days because in the processinf finding the solution, My machine basically died.I had to reinstall my development envirnomnat the OS on my handheld device, ActiveSync, and Fix some drivers for my usb Port. UGH. I didn't want to post this response until EVERYTHING was working and I coudl confirm that my found fix was true, and not only neccesary dur to a system corruption. I have now confirmed that to my satisfaction.


    I made this Change:

    {extensions}
    {bindingElementExtensions}
    {add name="pollingDuplex" type="System.ServiceModel.Configuration.PollingDuplexElement, System.ServiceModel.PollingDuplex"/}
    {/bindingElementExtensions}
    {bindingExtensions }
    {add name="pollingDuplex" type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement, System.ServiceModel.PollingDuplex"/}
    {/bindingExtensions}
    {/extensions}

    Where I added the Binding Extensions Section in addition to the BindingElementExtensions as Previously documented.

    Hope that helps anyone else.

    ReplyDelete
  43. Can anyone please guide me with a sample as to how to consume this service in a windows form application?

    Thank You
    Best,
    Alok Vad.

    ReplyDelete
  44. Alok, the client side of the polling duplex protocol does not have an implementation in .NET Framework, therefore it cannot be easily consumed from a windows forms application. One alternative to consider is adding an endpoint to the service that uses the NetTcpBinding, which provides duplex capability and is consumable from a .NET Framework client.

    ReplyDelete
  45. Thank you Tomasz for your guidance. I have one more question, I'm hosting ur solution under IIS 5.1 and IIS 5.1 does not support net.tcp binding. In this case how can I consume the duplex service in a windows form application.
    Thank You
    Best Regards,
    Alok Vad.

    ReplyDelete
  46. Alok, you can also use WsDualHttpBinding. Keep in mind, however, that this binding will create an HTTP listener on the client side, so the firewall(s) must be configured to allow incoming HTTP traffic to the client machine.

    ReplyDelete
  47. Thank You Tomasz. I appreciate your guidance.
    Best Regards,
    Alok Vad.

    ReplyDelete
  48. I have written an application based on your code, it was very helpful. I am having intermitted issues with not found error. I am only running this locally in debug mode in Visual Studio. I believe my issue has to do with creation and destruction of objects. I am opening a Silverlight child window that registers for several different Pub/Sub events. When I click a button on the child window, I publish an event and close the child window. This will work several times then will fail with a NotFound error. I think it’s a timing issue between request response and the code is no longer running when a reply comes back.
    Usually errors on
    public void EndSubscribe(System.IAsyncResult result) {
    object[] _args = new object[0];
    base.EndInvoke("Subscribe", _args, result);
    }
    Or
    public void EndPublish(System.IAsyncResult result) {
    object[] _args = new object[0];
    base.EndInvoke("Publish", _args, result);
    }

    I believe I am not disconnecting and connecting to the service correctly. Also my current design has each independent window subscribing for events and I am unsure that is a good decision.
    This is not just a notfound issue the code does run; I think it’s a timing issue. I do not know a solid way to cleanup when I close my child window. I create a class that does all the registering and publishing and updates a local list that is displayed. I have written functions to close the connection but when and how to execute them? I just publish a message then want to close.
    private void SetupPubSubClient()
    {
    _TableClient = new PubSubTableClient(
    new PollingDuplexHttpBinding(),
    new EndpointAddress(
    "http://"
    + App.Current.Host.Source.DnsSafeHost
    + ":"
    + App.Current.Host.Source.Port.ToString(CultureInfo.InvariantCulture)
    + "/TableService.svc"));

    _TableClient.PublishCompleted += new (TableClient_PublishCompleted);
    _TableClient.NotifyReceived += new (TableClient_NotifyReceived);
    _TableClient.SubscribeCompleted += (TableClient_SubscribeCompleted);
    }

    ….
    public void ClosePubSubClient()
    {
    if (_TableClient != null)
    {
    _TableClient.PublishCompleted -= TableClient_PublishCompleted;
    _TableClient.NotifyReceived -= TableClient_NotifyReceived;
    _TableClient.SubscribeCompleted -= TableClient_SubscribeCompleted;
    _TableClient.CloseAsync();
    _TableClient = null;
    }

    Any thoughts?

    ReplyDelete
  49. Steven, are your Subscribe and Publish methods one-way or request-response (i.e. do you have IsOneWay=true specified on the operation contract)? If the messages are one way, and if you are closing a window from which the message was sent immediately after sending it, chances are the Silverlight application will terminate before the HTTP stack has a chance to complete sending the message. I'd recommend one experiment: change the methods to be request-response (it is OK for the methods to return void), and then wait in the Silverlight application for the "response" before closing the window. I hope it helps.

    ReplyDelete
  50. Hi Tomasz,
    Can I use HTTP poling duplex for a voice chat or video conference..?I mean will this model support real time data..?

    ReplyDelete
  51. Tony, polling duplex does not support streaming, I don't think it would be an appropriate technology for real time voice or video. Apart from that, Silverlight 3 does not offer device integration that would enable this scenario (web cam, mike).

    ReplyDelete
  52. If I can read real time data from a local process via silverlight local connection,How can I stream that data over HTTP...? does the windows media server support duplex streaming of custom binary data..?if so how can I interface a silverlight server appplication with windows media server..?I thinnk flash media server has that capability..what do you think..?
    Thanks
    Tony

    ReplyDelete
  53. Thanks for the code, I’ve been playing around with it. Thought making the ‘guts’ of your PubSubService.svc abstract and have specific implementations for each ServiceContract. It’s running ok. Of course there would be singleton instances for each operation contract on the server using this approach.

    Bit tricky trying to get the ServiceContract interfaced (INotification) working in an abstract fashion, i.e. you can have specific ServiceContract interfaces inheriting this (and have the base class call BeginNotify) as they needs to explicitly specify the Action on the OperationContract. Just means each contract needs its only explicit ServiceContract interface. I just delegated the code that relies on the ServiceContract interface methods (BeginNotify and EndNotify) to the concrete implantations. It’s now seeming fairly flexible (until the point it’s totally inflexible LOL).

    One point, in your implementation PubSubService.svc.cs, you wire up a couple of events on the current channel:
    OperationContext.Current.Channel.Faulted += new EventHandler(this.Unsubscribe);
    OperationContext.Current.Channel.Closed += new EventHandler(this.Unsubscribe);

    How does these get unwired? Will this prevent the Current channel from being GC’ed?

    (again thanks for the code :))

    Keith

    ReplyDelete
  54. Tony, if you descriebed your scenario in more detail I would be able to better answer your question. What is the problem you need to solve? There are many more communication technologies available on the windows server than on the Silverlight client. It is also not entirely clear to me what you mean by "Silverlight local connection".

    ReplyDelete
  55. Anonymous, the goal of the subscription to the Faulted and Closed events is to clean up any in-memory state associated with a session the server may have. Keeping these subscribtions in place should not prevent the channel from being garbage collected whent he session is closed or faulted.

    ReplyDelete
  56. Hi Tomasz,
    My scenario is like this.I have an application sharing program.It is implemented in client side as activeX controls.There is a sharing module and a viewing module.Both are running in browser.There is a central conference server .Both conference server and client support only TCP.The conference server is a custom implementation with limited scalablity.So I want to change the server to a .NET compatible low cost media server(or any other server including IIS which serve the purpose),by .NET compatible I mean I can write some code in .NET to make conferences etc and route the communication to conference members only.I also need duplex communication for remote controling the shared application.And most important I need HTTP support.So dear friend pls help me with your valuable advice
    Thanks
    Tony

    ReplyDelete
  57. Tomasz,
    One more requirement, I need to use sliverlight in browser insted of my activeX control(mainly the viewer).I hope the sliverlight client can communicate with my activeX sharing component
    Tony

    ReplyDelete
  58. Tony, currently Silverlight does not support real time communications (for example, it has no camera or microphone support). One Microsoft product that comes to mind that might satisfy your scenario is http://office.microsoft.com/en-us/communicationsserver/default.aspx. I am not an expert in live communication, you may be better off asking your question on one of the forums related to Live Communication Server or Live Meeting at http://www.microsoft.com/office/community/en-us/FlyoutOverview.mspx#14.

    ReplyDelete
  59. Ok Thanks Tomasz..
    The live communication serevr is too costly to approach..One question, does silverlight client support TCP connection..?
    Tony

    ReplyDelete
  60. Yes, Silverlight 3 supports TCP through the Socket class, although the port range number is limited. Check out http://msdn.microsoft.com/en-us/library/cc296248(VS.95).aspx.

    ReplyDelete
  61. Tomasz,

    Thanks for the article. I have a working service using the duplex binding talking to SilverLight. I need it to also publish events to a windows service client. To do that I believe from your previous answers to Alok that I can use WsDualHttpBinding. What I don't understand is how to structure the project to support both bindings in the same web site. Is there an example of how such a project could be structured and/or could you steer me in the right direction?

    Thanks!

    - Art

    ReplyDelete
  62. Art, WCF has been designed to support exposing a single service over multiple endpoints, where each endpoint may be using different bindings. Adding an endpoint for WsDualHttpBinding to your service that already contains an endpoint for PollingDuplexHttpBinding is possible with configuration change - no change in code should be necessary. Check out the documentation at http://msdn.microsoft.com/en-us/library/ms751515.aspx for how to do it.

    ReplyDelete
  63. Unfortunately it looks like this method doesn't work in Opera 10...

    ReplyDelete
  64. Silverlight 3 does not support Opera. The list of supported platforms can be viewed at http://en.wikipedia.org/wiki/Microsoft_Silverlight#Operating_systems_and_web_browsers.

    ReplyDelete
  65. There is a bug where if the clients are closed before the publisher stops publishing the server never unsubscribes them. I can provide a zip file with the fix if you would like.

    ReplyDelete
  66. James, thank you for finding a bug. Could you describe it along with a workaround in a comment?

    ReplyDelete
  67. Thank you for your response from my last question. It was very helpful.

    I have implemented your code for pub/sub client, and I need the client to be able to maintain connections.
    The volume is low and inactivity would be an issue and I would like not miss messages.

    Right now the client code gets an "InnerChannel_Faulted" error after 10 mins of inactivity.

    Can you point me to what i might need to do to accomplish this.

    Thanks,
    Steven

    ReplyDelete
  68. Tomas, many thanks for the great series of articles you've been doing on Silverlight/WCF scalability. It's been very helpful.

    I do have a question. We've been using Entity Framwork generated classes as our data transfer objects. They're a tad more heavyweight than I'd like, but they're also (reasonably) simple to use, and they seem to have worked well for us so far. However, I can't seem to figure out how to use them with the pre-serialized pattern that you're recommending. Specifically, it seems like your recommended approach is to share the file that contains the DTO definitions between the client and server, and of course, that won't work with EF-generated objects. Is there another way to do this that I'm just missing? Or if I want to take advantage of pre-serialized objects, do I need to switch to using a separate DTO layer on top of the EF classes?

    Thanks again for your help.

    ReplyDelete
  69. Steven J, I just answered a similar question to yours related to my article about polling duplex scalability at http://tomasz.janczuk.org/2009/09/scale-out-of-silverlight-http-polling.html. Pasting below for convenience:

    The bottom line is that the HTTP protocol does not provide any delivery guarantees, and polling duplex protocol inherits lack of this assurance. If your application requires delivery guarantees, you should take appropriate measures at the application level to provide it (for example, retries). When a TCP connection underlying an HTTP long poll is dropped, all WCF duplex session channels tunneled through that long poll request (i.e. all channels created to the same server scheme/host/port combination) will be faulted. The application logic on the client should ensure the channels are re-created if it is desired. Please also note that HTTP proxies sometimes decide to terminate inactive TCP connections, which will cause the behavior above. A mitigation built into the polling duplex protocol uses the ServerPollTimeout (default of 15 seconds) as a maximum period after which the server will respond to the long poll even if there are no messages to send to the client. Setting the ServerPollTimeout to a lower value will reduce the risk of dropped connections at the cost of increased network traffic.

    ReplyDelete
  70. Ken, the approach of sharing the data contract files I described works for simple types, typically authored by hand. Since Entity Framework classes cannot be used verbatim in Silverlight, the best approach I can think of is to generate a silverlight proxy to a WCF service that exposes them using Add Service Reference or slsvcutil.exe. This will generate data contract types on the Silverlight side that are wire compatible with the Entity Framework types on the server.

    ReplyDelete
  71. Thank you for the reply (and replay). I guess my real question: Is there a proper way for a client to close it's connections and reopen after a loss of communicaiton is detected(from the context of your sample).
    Is a restart just:
    client.CloseAsync();
    new client();
    client.SubscribeAsync("topic");

    (Can you recommend a good book?)
    Thanks again,
    Steven

    For other people: I believe some of my issues where because I was running in debugger.

    ReplyDelete
  72. Sorry for the last post,
    I think I will just read your other article.

    Steven.

    ReplyDelete
  73. Tomasz,

    What about the reliability of the PollingDuplexHttpBinding?

    Actually, I know it does not support realiability. Maybe my question would sound better: "What does an unreliable binding mean?".

    There are people describing the lack of reliability like a "chaos":
    - messages that are not delivered;
    - the same message delivered more than once;
    - unordered messaging;
    On the other side, there are people saying there are very little applications that really need realiability.

    I got a little confused; I don't know what to belive.

    I need to use the PollingDuplexHttpBinding and I would like to know what are the risks of using this binding; I need to decide what is acceptable for my application and how much reliability do I have to implement at the application level.

    Thank you !
    Ernest

    ReplyDelete
  74. Ernest, as I said in response to a similar question a few answers back, the polling duplex binding in general has the same reliability gurantees (or lack thereof) as the underlying HTTP protocol. Despite the fact the programming model is based on WCF sessions, there is no gurantee that messages will arrive on the client in the same order they were sent from the server; there is no detection of lost messages; there is also no guranantee a message will be delivered only once. In practice, I have not seen lost messages other than in day-long stress runs (and "losing a message" in case of polling duplex protocol will be usually surfaced as a channel fault); I have also never seen out of order delivery or more than once delivery. In the vast majority of application scenarios I have seen I would expect these de-facto delivery "guarantees" to be sufficient. At the same time, in cases where losing a message, receiving a message more than once or out of order has unaccaptable consequences, I would definately devise a reliability messaging layer on top of the polling duplex protocol.

    ReplyDelete
  75. Hi Tomasz,
    what are the steps(in all dimentions i.e silverlight client, ajax client and polling duplex service ) to make the service secure using ssl i.e using https instead of http.

    thanks
    Jamal.

    ReplyDelete
  76. dear sir
    I m vivek from India and i m developing an Online Examination system in C#.Net and i need to copy few files on client machine so tht test should not break even if internet connection gets disconnected.
    So my question is how can i copy files to client machine without actually acknowledging him or even he comes 2 know it, its ok
    I dont know anything about WCF, will this be useful in my application
    I m stuck for last 4 days. Plz help...

    ReplyDelete
  77. Hi Tomasz,
    Can we make a none silverlight client program (such as WCF library and it's hosted by Windows Service) call the PubSubService.svc to publish a topic?

    ReplyDelete
  78. Hi Tomasz,
    Can you add some other features into the demo?
    1. add Unsubscribe in the service and expose it to the client
    2. PubSubClient can change the topic at any time.

    I try to add a unsubscribe service myself but has some problem. Each time when the same client call the service function, I will get different sessionID, I don't know to identify the client in a unique ID.

    ReplyDelete
  79. Never mind, I found the solution of my previous post.

    ReplyDelete
  80. Nice info.If you want to have your own website, it is necessary to host your website on a web server. Company that provides the web servers to host your website is called web hosting providers.

    ReplyDelete
  81. I am looking at this project with a co worker and I am beyond frustrated as I cannot get this sample to run successfully. I have tried the GAC with no success, and I have removed the App.Current.Host Calls as they seemed to not be working. Now when the system finally does run I am getting cross domain errors? Any ideas I am at my wits end in looking at this example. Also Silverlight 3 SDK is installed!

    ReplyDelete
  82. Same guy with regards to previous post. I finally got the thing to work, I had to do exactly this. http://www.wintellect.com/CS/blogs/pmehner/archive/2009/10/25/migrating-polling-duplex-binding-element-from-silverlight-v2-0-to-v3-0-for-wcf-services-in-the-cloud-code-samples.aspx

    The Service project is referencing the old version but setting Copy Local to true was the only thing that worked after the new one was added.

    ReplyDelete
  83. I'm still getting the "The remote server returned an error: NotFound." error when I try to subscribe to a topic. I already cleaned the 3 solutions and rebuilt but no luck. I'm using VS2008 SP1 and SL3. Any other suggestion?

    ReplyDelete
  84. Ok solution just above my first comment worked. Thanks Anonymous!

    ReplyDelete
  85. I really enjoyed your post and have it working with HTTP. I need to use https so i made the following changes without any luck. Did I miss something obvious?

    1) In web.config I changed the binding from mexHttpBinding to mexHttpsBinding.
    2) changed httpTransport in to httpsTransport in custom binding.
    3) Added changed http to https in the client endpoint address.
    4) changed client binding to CustomBinding binding = new CustomBinding(new PollingDuplexBindingElement(),new BinaryMessageEncodingBindingElement(),new HttpsTransportBindingElement());
    Thankyou, James

    ReplyDelete
  86. James, the two extra steps that come to my mind without knowing in what way your solution does not work are: 1) you need to configure an X.509 certificate to use for server authentication on the server side. 2) you may need a clientaccesspolicy.xml on the server if the page contaning the Silverlight application is exposed on HTTP while the polling duplex service on HTTPS - calls to the polling duplex service will be considered cross-domain.

    ReplyDelete
  87. Hello, your service and silverlight are tightly integrated, I want to put just the service on IIS and use silverlight locally is their anyway I can do that?
    Nik

    ReplyDelete
  88. Anonymous, you can build an out-of-browser client using Silverlight. Check out http://msdn.microsoft.com/en-us/magazine/dd882515.aspx to get started.

    ReplyDelete
  89. Hi Tomasz,

    I have a scenario where a Web Application hosts a WCF http polling duplex service. In the web.config I have registered the pollingDuplexHttpBinding extension:

    {services}
    {extensions}
    {bindingExtensions}
    {add name="pollingDuplexHttpBinding" type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement, System.ServiceModel.PollingDuplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"}

    and established a binding configuration for the endpoint,

    {bindings}
    {pollingDuplexHttpBinding}
    {binding [name, etc...]}

    So far so good. But this Web Application is also a consumer of an external service; so the Web Application itself contains a Service References folder with an "ExternalService" entry.

    Now the problem: from this Web Application, I am not able to perform "Update Service Reference" on "ExternalService". If I attempt to do so, I receive this error in Visual Studio:

    Configuration binding extension 'system.serviceModel/bindings/pollingDuplexHttpBinding' could not be found. Verifiy that this binding extension is properly registered in system.serviceModel/extensions/bindingExtensions and that it is spelled correctly [line 109]

    Line 109 of my web.config is the {pollingDuplexHttpBinding} opening tag.

    In the Web Project's bin folder, I do have a copy of System.ServiceModel.PollingDuplex.dll, copied from the ..\Microsoft SDKs\Silverlightv4.0\Libraries\Server folder. I also do not have any other Silverlight SDKs installed on this machine apart from the Sliverlight 4 9/2/2010 SDK.

    Do you have any suggestions that might allow me to "Update Service Reference" on "ExternalService" from this Web Project? The ExternalService is in development and so requires a mild amount of updating.

    ReplyDelete
  90. with, this is a known issue we are working to resolve in the future. In the meantime, unfortunately the best you can do is to comment out the polling duplex sections in the configuration file, run the update service reference function, and uncomment the polling duplex sections back.

    ReplyDelete
  91. Ok - thanks for confirming that. It's not too bad to comment out the setting a few times per day, even if it's not ideal.

    I'm looking forward to Visual Studio getting along better with the polling duplex binding in the future :)

    Thanks for the reply!

    ReplyDelete
  92. Hi Tomasz,
    for removing clients in the server, I set inactivity and receive timeouts to 5 minutes
    and in the client app, I have a timer that sends a message to the server every 4 minutes until the server knows this client is connected or not,
    is this good?

    ReplyDelete
  93. Mahdi, that sounds right from the perspective of keeping the connection alive at the application level. Keep in mind, however, that at the HTTP long polling/TCP level the connection may still be faulted depending on the behavior of network intermediaries. If you application really requires constant connectivity, it is advisable to implement some form of re-connect logic should the connection fail.

    ReplyDelete
  94. "it is advisable to implement some form of re-connect logic should the connection fail"

    Tomasz,I have a singleton factory class in the client app(i use these class for using my chat service in all of the app) and in that class there is a property that return my chat service but before returning checks if it's null creates service and if it's state equales closed/faulted then opens it.

    public ChatServiceClient ChatServiceClient
    {
    get
    {
    if (m_ChatServiceClient == null)
    {
    m_ChatServiceClient = new ChatServiceClient(new PollingDuplexHttpBinding(PollingDuplexMode.MultipleMessagesPerPoll),
    new EndpointAddress(string.Format("http://{0}:{1}/Services/{2}", App.Current.Host.Source.DnsSafeHost,
    App.Current.Host.Source.Port.ToString(CultureInfo.InvariantCulture), "ChatService.svc")));
    }
    else if (m_ChatServiceClient.State == CommunicationState.Closed || m_ChatServiceClient.State == CommunicationState.Faulted)
    m_ChatServiceClient.OpenAsync();

    return m_ChatServiceClient;
    }
    }

    do this work good for solving connection fails?

    Thanks

    ReplyDelete
  95. Mahdi, it does not work: a WCF proxy that has been closed or faulted cannot be opened again. You need to create a new instance instead.

    ReplyDelete
  96. Tomasz,
    Thank you for the quick responses and great info.
    James

    ReplyDelete
  97. OK-and if I create a new instance I have a new sessionId,yes?
    finally I haven't problem with changing sessionId because I used user names for identify and can change the sessionId property of my clients in the server with a special userName after I create a new instance of my proxy.

    Thanks a lot Tomasz

    ReplyDelete
  98. Mahdi, creating a new polling duplex proxy instance on the client will result in a new sessionId.

    ReplyDelete
  99. Tomasz I learn more with your great and quick responses, Articles and video.

    Very Thanks

    ReplyDelete
  100. Hi Tomasz,

    thanks for such nice explanation...

    we are using pubsub implementation and we have 3 different pubsubs services hosted in iis7 under same application pool..

    we are facing some problem with it..actually when we see the data in client side with fiddler...we could see the messages are mixed for the services...one service data is coming from other service...

    for example alarm service is sending data for trend service...which is not expected..even we do have different class objects for different services

    can u please suggest what could be the reason for it..

    Thanks.

    ReplyDelete
  101. Sumeet, even if you have several client proxies calling several services using the HTTP polling duplex protocol, you shoudl only ever see up to one outstanding HTTP long poll request. Regardless what the request URL of the HTTP long poll is, we multiplex notifications sent from any of the backend services onto the poll response. The notifications should be correctly dispatched to appropriate proxy instances on the client side. This mechanism is meant to minimize the TCP connection use in a browser enviroment, since browsers impose a quota on the maximum number of concurrent HTTP requests to a single backend server.

    ReplyDelete
  102. Hi Tomasz,

    What's the difference between HTML5 WebSockect API
    and WCF Polling Duplex?

    For creating a chat application which is better?
    As you say, in a HTTP long polling, the server may be faulted, is this right for WCF polling duplex with net.TCP binding and HTML5 WebSocket API?

    I saw flash chat rooms work well in duplex communication what api uses for flash duplex communication's?

    Finally, if you want to create a real web chat, Which would you use(in Silverlight)?

    thanks

    ReplyDelete
  103. Thanks for quick response...

    If my understanding is correct this is expected what we could see in Fiddler..the multiplexing of the messages.it gets de-multiplexed and sent to the respective clients ..regardless of the the request URL.

    we need not worry about it..correct?

    ReplyDelete
  104. Mahdi, WebSockets is an upcoming protocol standard for duplex communication on the web, and it is going to be far superior to any http long polling solution, including HTTP Polling Duplex in Silverlight. Check out http://tomasz.janczuk.org/2010/07/silverlight-html5-websocket-client-with.html for more information.

    Note that as of today WebSocket implementation is not available in .NET Framework or Silverlight.

    All Flash based solutions I have seen are using one form or another of HTTP long polling, but I would not be surprised to see a websocket implementation as well at this point.

    There is more to a chat application than just a duplex messaging capability either websockets or http long polling protocols provide. You need to organize your message flow such that messages are exchnaged between clients, not just between the server and a client. Chat applications I have seen typically use a publish\subscribe message exchange pattern (that utilizes a duplex messaging protocol underneath for low notification delivery latency). One pub\sub solution suitable for implementing chat with Silverlight clients (or JavaScript clients) is at http://laharsub.codeplex.com. Check it out.

    ReplyDelete
  105. Sumeet, yes, in Fiddler you should be able to see the multiplexing in action: each HTTP long poll contains two pieces of information: the client ID that uniquely identifies an instance of a Silverlight application, and a session ID that uniquely identifies an instance of a client proxy within this application. Every message in the HTTP long poll response targets a specific session ID. You can read more about the protocol itself at http://tomasz.janczuk.org/2009/09/scale-out-of-silverlight-http-polling.html.

    You should not worry about this mechanism working correctly our of the box, unless we have not done our job right testing it. If you find an issue, please let me know.

    ReplyDelete
  106. Hi Tomasz,

    Thanks for nice articles about the Silverlight polling duplex.

    We're developing a platform were we're using pollingDuplex a lot for sending different commands (strings) from a WPF-desktop client over Net.TCP binding to Silverlight 4 clients.

    I guess that makes the service a pub/sub service. We've implemented many of your suggestions in this article and also in your article that talks about performance in polling duplex.

    We also have reconnecting logic in the clients and the clients ping the service every 15 seconds to tell the service that the client is still alive. If the ping does not succeed the client reconnects.

    A major problem we're facing now is that when we connect many clients everything becomes very unstable. When more than 400 clients (approx) are connected clients begins disconnect and reconnect randomly.

    Also, the Net.Tcp connection for the desktop client becomes very unstable and faults a lot.

    When observing the CPU load on the server it looks good so I does not think that is the problem. The problems are actually only present when nothing is sent from the publishing client.

    However, if commands are sent from the desktop client to the service (and published to the SL-clients) at a higher frequency (about once every 5 seconds) the clients doesn't disconnect but instead seems to stay connected (even if there are more than 400 connected).

    Can you draw any conclusions out of this? Can it be some timeouts that are configured in the wrong way?

    Any ideas?

    The service log file doesn't provide much information.

    Help will be much appreciated!

    /Kristian

    ReplyDelete
  107. An update to my previous post:

    To achieve so many clients we had to start multiple instances of internet explorer on each computer (around 5). It seems that this can be the cause of the problem because when I tried on only one computer with multiple instances it seems to be a breakpoint at around 5 instances before clients starts to disconnect and reconnect.

    Do you have any clue why multiple instances of the application on one computer can cause the system to behave like this?

    Thanks for help!

    /Kristian

    ReplyDelete
  108. Kristian

    Let me make sure I understand your scenario: a WPF client is sending messages to the server using net.tcp binding. The server is forwarding these message to multiple Silverlight 4 clients using the HTTP polling duplex binding. Is that correct?

    One possible reason for the system to "disconnect" clients is that a networking component decides to terminate inactive TCP connections. This theory seems to be supported by the fact that the system under some load is stable. Two great tools that help to understand what is going on at the protocol layer are Fiddler2 (http://www.fiddler2.com/fiddler2/) and NetMon (http://www.microsoft.com/downloads/en/details.aspx?FamilyID=983b941d-06cb-4658-b7f6-3088333d062f&displaylang=en).

    HTTP polling duplex protocol has a number of timeouts that may affect the behavior you are seeing. A comprehensive documentation of those is at http://blogs.msdn.com/b/silverlightws/archive/2010/07/16/pollingduplex-multiple-mode-timeouts-demystified.aspx.

    Lastly, the messaging pattern in your application indeed resembles a publish\subscribe flow. One technology that can be helpful in addressing the needs of your application is http://laharsub.codeplex.com. Laharsub is a pub\sub messaging server based on HTTP long polling. It comes with Silverlight, .NET, and jQuery clients.

    ReplyDelete
  109. It was noted in an earlier comment, that clients that are shutdown, are not "unsubscribed" on the server. the Original poster hinted at a solution but didn't offer one. I can't seem to find a place to discover that the subscribing client is no longer there. I would have expected some sort of exception on executing the callback.

    ReplyDelete
  110. Hi! Can I use this duplex for a WPF client application? What about a xbap WPF application? Thanks! Bogdan I.

    ReplyDelete
  111. Bogdan, unfortunately there is no .NET client implementation of the HTTP polling duplex protocol from Silverlight, so you cannot call into a polling duplex service from a WPF application. You may want to check out http://laharsub.codeplex.com, an open source message server that is based on http polling duplex and comes with a .NET client (as well as Silverlight and jQuery).

    ReplyDelete
  112. Hi Tomasz thanks for answering previous posts that helped a lot....

    One more concern we have now when we send large amount of data to the silverlight client it is not able to receive..it goes to faulted state...can u please suggest the cause of it and how we can resolve it...
    thanks

    ReplyDelete
  113. Sumeet, there is a number of quotas that may affect this behavior. What is the size of the message you are sending? Are any exceptions thrown? Does Fiddler2 provide any insight into whether the message is leaving the server or not?

    ReplyDelete
  114. Hi Tomaz, First many thanks for you.

    Please I have a question, when I set duplexMode="MultipleMessagePerRole" and serverPoll="00:01:00" for testing purpose I got the clinet channel Faulted event fired when the serverPoll timeout reached. When I dont set duplexMode,however, the channel Faulted event does not fire. Please could you explain for me this issue! And also "Sorry for that" could you explain what do we mean by Polling either server or client. I've read many msdn articles related to it and to the timeouts but am not feeling myself really understand it.

    Thanks in advance, and I really appreciate your hard work...

    ReplyDelete
  115. Hello! I still can't fix the .dll problem. Where is located the right file that should be added to the refference?

    ReplyDelete
  116. Hie tomasaz janczuk,


    The remote server returned an error NotFound

    i dont knw what m i doing wrong..

    whenever i try pollingduplex i got this error on each and every application
    even this one which u provide above.

    i have all the solution which is given for this type of error above but nothing works please help me out

    ReplyDelete
  117. Hi Tomasz,

    I have done so much research on this now that I am bleary eyed and getting frustrated. I am simply trying to get Http Polling Duplex working within a .net framework 4 wcf service for use with a Silverlight 4 client.

    I have followed several instructions including this one ( http://msdn.microsoft.com/en-us/library/cc645027(VS.95).aspx ) and several others. I have verified that I am referencing the correct version of the System.ServiceModel.PollingDuplex DLL. I really don't know what else I can do at this point.

    I have received the "Contract requires Duplex" and the "pollingDuplex not valid" errors at different times. Is there any way you could post a Pub/Sub sample that works in .net framework 4/Silverlight 4?

    Thanks!

    ~Matt

    ReplyDelete
  118. Hello Tomasz,

    I am facing a scenario where Client Channel is getting faulted at random intervals. At this point if try to run the service in browser it gives me the error "The contract name 'MyApp.Interfaces.IPubSub' could not be found". I am using fully qualified name of interface in web.config file. I have to either add back the reference to System.ServiceModel.PollingDuplex dll or restart World Wide Web Publishing Service. I have been unable to find any solution to this for some time now. Could you please explain the cause and suggest a solution ? Thanks.

    Omer

    ReplyDelete
  119. Hi Tomasz

    I have a working service and client application implementing Polling Duplex targeting the Silverlight 4 runtime and it works brilliantly. I'm now trying to implement the same technique in a SL 5 application and my client throws an exception when trying to instantiate the service reference client object; "the given key was not present in the dictionary". In my SL4 app I declare the client endpoint config in the ServiceReference.ClientConfig file so that I could modify timeout settings. When I do the same in the SL5 app, it complains about not being able to load ServiceModel.PollingDuplex.dll. I presume the "key not present" exception is because the client doesnt know about the pollingDuplex element in the client config file? What has changed in how PollingDuplex works in SL5 that would stop it behaving as it did in 4? I've looked at all the runtime versions of the ServiceModel, ServiceModel.PollingDuplex and SeviceModel.Extensions dll versions between the SL4 and SL5 runtime and they're the same, so it should be exactly the same code running. Its very perplexing. Do you have any thoughts? Help would be appreciated :)

    ReplyDelete
  120. I got this working, seems I had a mixup between SL 4 and SL 5 assemblies. Everything now works as expected. ;) I still get a Visual Studio error when I try to update the service reference however, about pollingDuplex (the name i gave my registration of the pollingDuplexHttpBindingElement in the Extensions section of the server web.config) not being a recognized element. I have to remove the entire system.serviceModel tag from the clientConfig before it will update the service reference successfully, and then put it back. Any idea why this happens?

    ReplyDelete
  121. I would like to thank you for the efforts you have made in writing this article. I am hoping the same best work from you in the future as well. In fact your creative writing abilities has inspired me.
    Chan Ming

    ReplyDelete
  122. This is an awesome advancement. For more focused mode, this functionality is very necessary. Thank you for posting and sharing.

    Paul Bola : - Hello california hire Mr. Paul Bola, he is very nice and honest person, he is a gentlemen who work as a professional, I already worked with Mr. Paul bola and I am happy to work with him.


    Paul Bola found Hilltop Creative Group, a leading web based company in United States. A talented and professional team of HilltopCG uses their skills to promote your business and achieve your goal. Our team design your website and serve you in Website redesign, Branding, Web development, Search Engine Optimization, Mobile application design, Hosting, Maintenance, Google places.

    Paul Bola promises to complete his responsibility and dedicatedly providing top quality web services to clients. We have a Quality control team that ensures the client’s satisfaction and support all time. A team of successful people is key to make a company successful, HilltopCG having such talented team of successful people to provide superior services to our clients.


    Visit Paul Bola Profile :-

    Linkedin :- Paul Bola

    Facebook :- Paul Bola

    Link: - Paul Bola

    Site: - Paul Bola

    IMDB :- Paul Bola

    Blogger :- Paul Bola | Paul Bola | Paul Bola

    ReplyDelete
  123. Hi Tomasz,
    I saw your video regarding Polling duplex on channel 9 and it was awesome. I started creating a chat application in Silverlight on polling duplex and everything is working fine multiple users are chatting simultaneously. I have noticed a thing that if two users have started a chat on their respective chat window and after a long idle time they again start chatting no user receives any reponse. I don't know why whether it is related with Timeout. I set Inactivity and ReceiveTimeout and even OperationTimeout but no change. The start is good but if we get in idle state and then start again then no response is there.

    ReplyDelete
  124. I really like the article.But I want to introduce you the ken griffey shoes.It is so nice.I just find it by chance.griffeys are good quality.The price is cheap .You can go to see about ken griffey jr shoes.Really attractive. ra bodybuilding |
    ra sculptor review

    ReplyDelete
  125. i have read your blog and find that your articles are amazing, i have added this into my bookmark. thanks a lot. ra hcg | ra dynasty

    ReplyDelete
  126. It was nice to read your articles. The thoughts are very well laid out and it was refreshing to read. I was able to find the information that I was looking for. I just wanted to leave a comment as a token of appreciation. ra focus

    ReplyDelete
  127. These are truly enormous ideas in about blogging. You have touched some fastidious factors here. Any way keep up wrinting.
    Doctor califonia | online doctor appointment | Find Doctor

    ReplyDelete
  128. An interesting discussion is worth comment. I believe that you must write extra on this matter, it won't be a taboo topic however typically individuals are not sufficient to speak on such topics. To the next. Cheers Sofa Dealers Mumbai

    ReplyDelete

My Photo
My name is Tomasz Janczuk. I am currently working on my own venture - Mobile Chapters (http://mobilechapters.com). Formerly at Microsoft (12 years), focusing on node.js, JavaScript, Windows Azure, and .NET Framework.