Using reactive extensions for a push-based client-server communication with Silverlight and WCF
8 minutes read
In the previous article, I explained you how Rx can improve the process of downloading data from a WCF service. This was a classical scenario where the Silverlight client explicitly asks for data from the server.
Now we will see how we can use Rx in a push based scenario where the server sends data to the Silverlight client without any explicit demand from it.
In order to follow this article you need to make sure you have the latest version of Rx and the Silverlight SDK. At the time theses lines were written I was using Silverlight 4.0.60310.0 and Rx 1.0.10621.0.
We want to create a Silverlight application and a WCF service that pushes temperature data in the Celsius scale to the client at random intervals. The Silverlight application (aka client) has two independent modules, one for displaying the temperature received in the Celsius scale and the other one to display it in the Fahrenheit scale. Even though we have two independent modules, we want them to use the same connection to the WCF service to receive the temperature. The module will also have no direct reference on the WCF service proxy allowing us to use dependency injection and unit testing of the modules’ view models.
A duplex service is a service where both the client and the server can send data through the same connection which is exactly what we want here. We chose to create a service using the Subscribe-Publish pattern. The client will create a connection to the server using a Subscribe method and then wait asynchronously for data from it.
In WCF, this kind of scenario is made possible by using a service callback. This callback is an interface defined in the server side and implemented at the client’s side which the server will use whenever it wants to send data to the client.
In order to use these callbacks we need to choose a compatible WCF binding. When creating a WPF application we can use all the bindings provided by default such as wsDualHttpBinding but in Silverlight we are somewhat restricted. In Silverlight we can use netTcpBinding or pollingDuplexHttpBinding.
The first one is a little bit harder to configure than the second one and I will write about it in another post. For today, I’ll focus on the second one.
This binding is a little bit special because it’s a duplex binding over an http communication. As it is well-known, http is not a duplex communication protocol. In http the client has to explicitly ask the server for data. When we need to have such a duplex communication using Silverlight we can implement a custom polling code. Polling is the process where the client regularly asks the server whether some new data is available or not. The pollingHttpDuplexBinding already implements the polling code for us directly inside the communication layer improving the performance of the overall process.
The pollingHttpDuplexBinding is not included by default in Silverlight or WCF. We can find the assemblies for the client and the server in the Silverlight SDK. On my hard drive theses dlls are located in the C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries folder so for you it should be there C:[ProgramFilesArchitecture]\Microsoft SDKs\Silverlight[SilverlightVersion]\Libraries.
There is two assemblies required for this binding to work, one for the client and the other one for the server.
In the web project hosting the Silverlight application we add a reference to the server’s System.ServiceModel.PollingDuplex.dll and in the Silverlight client we add a reference to client’s System.ServiceModel.PollingDuplex.dll.
Creating the service
In the web project we first create two interfaces defining the WCF contracts for both the service and it’s service callback.
Then we can create an implementation of the service (this implementation is a simple one that would not suit for production needs). This implementation creates a timer that will call the service callback of each clients connected to the services to send new random temperature data.
In this implementation you have to focus on two things :
OperationContext.Current gives us information about the client that has called the current executing service method. client.GetCallbackChannel gives us an instance of the service callback to use in order to send data from the server to the client.
Then we expose our service using a .svc file. In my example the svc file looks like this :
Finally we need to configure the binding in the web.config file, here’s how the serviceModel section is looking :
We’re now done for the server side.
Using the service in Silverlight
First let’s add a reference to our previously defined service and let’s define it’s namespace as TemperatureServer.
The tool used by Visual Studio to generate the service proxy correctly generates the needed classes but doesn’t generate a proper ServiceReferences.ClientConfig file. By not proper I just mean empty.
So let’s configure the reference by ourselves (don’t forget to replace the endpoint addresses by yours).
We will now create a TemperatureService class that will wrap the WCF service proxy as an observable service. This class is a singleton (be free to use any dependency injection libraries instead of a singleton) that will be used into every modules (Celsius and Fahrenheit) to call the web service.
Here’s how it looks like :
In the constructor we create an observable that will call the SubscribeAsync method of our WCF service once. Then, every time our observable of temperatures is subscribed to, we register to the PushTemperatureReceived event of the WCF proxy class. The lambda we use here to register to the event just pushes the temperature received into the observable by using the OnNext method of its observer. And that pretty much it, all the magic happens here. Now every time we received a temperature from the server, it will be available to all the subscribers of the observable.
I created two views for displaying the temperatures in Celcius and Farenheit. Here’s their XAML code :
Here’s how I used it in the main view :
Each of the temperature views has it’s own view model. Here’s their implementation :
That’s pretty much it. Everything already works fine with that. Each of the view models subscribe to the Temperatures observable defined in the TemperatureService class we created earlier and just refreshes their own temperature property with some conversion calculation for the Fahrenheit view model.
We have now a duplex service used by Silverlight that will work over the classical http protocol. We use the reactive extensions to simplify our code and to share the same network resources across different view models that needed the same information at the same time.
I find it pretty sexy and you ?
As usual you can find the code used in the example in my skydrive.