Reactive, Silverlight, and Web Services (Oh my!)

OR:

A simple example of how to use the Reactive Extensions with Silverlight to process responses from web services.

One of the most useful tools that I have stumbled across in recent months has to be the Reactive Extensions (Rx) put out by Microsoft Labs. There are smarter people than me out there who have done a much better job of explaining WHAT Rx is (check a couple links in the Additional Reading section), so I won’t be stepping over into that realm, but rather I will be breaking down one way of utilizing Rx for use in Silverlight.

One word that is borderline synonymous with Silverlight is Asynchronous. Everything that you will end up doing in Silverlight is going to be Asynchronous, illustrated by the complete lack of IO blocks available from within your application.

From a UI standpoint, this is no problem. Once the application is downloaded and running, everything pretty much manages itself and you can go about your merry way. But what if you wanted to connect your application to, well, anything? Say you really wanted to get a little bit of real time information out of a database. This normally means delving into callback hell. Ok so maybe I’m being a little dramatic, but no one really enjoys writing up callback and handlers and what-not.

Enter the Reactive Extensions. Rx takes the brunt of the workload, and streamlines your coding, making for easier reading (once you understand what is going on). It is probably a good idea to have a solid understanding of lambda expressions and / or anonymous delegates. I’ve added a section at the end entitled Additional Reading, and added a link there.

This example requires that you have Visual Studio installed and functional, as well as Silverlight, AND the Rx Framework for Silverlight (link in the Additional Reading section). Also it would be a really good idea to have a web service either created and ready, or added to your project. I won’t be going into web services at all, as we will only be discussing what to do with the returned results.

The first thing I did was create the UI. I just wanted a really simple form with a textbox and a button that looks like this: UI

No trickery here. Just a textbox control and a button control placed in a stack panel. Basically we are going to use the button to kick off the data request which is going to in turn fill up our textbox.

On to the code. Create a new method that is hooked up to the Click event of the button. We are going to use the button click to initiate our call.

The very first thing that we have to do is define our “Observable” object that will *react* to the events of the web service call. In Silverlight we only have access to the “Observable.FromEvent” method, which we can use like this:

var results = Observable.FromEvent<GetTopRevenueCompletedEventArgs>(

      completed => client.GetTopRevenueCompleted += completed,

       completed => client.GetTopRevenueCompleted -= completed )

       .ObserveOnDispatcher();

This looks a little crazy, but it really isn’t all that bad. In my example ‘result’ is an IObservable object that is created “FromEvent”, the event type being “GetTopRevenueCompletedEventArgs”, which is the completed event args of the method that I’m calling in my web service. The next two lines define the addition and removal of my GetTopRevenueCompleted method, which the observer is going to be listening to, and then the final line makes sure that the observer runs on the UI thread. Nothing really crazy here, we’re just defining WHAT we’re observing.

The next step is to actually tell it what to do:

results.Subscribe(

action =>

       {

              var returnedResult = action.EventArgs.Result.Values;

              foreach ( var item in returnedResult )

                     this.Results.Text += Environment.NewLine + item.Revenue;

                },

        e => this.Results.Text = “Error downloading…” + e.Message,

        () => this.Results.Text += Environment.NewLine + “ALL DONE!!!” );

Now THIS is starting to look a little crazy. What’s going on here? Once again, there’s no voodoo magic as long as you take a second to read what’s actually going on. What we have is a series of 3 lambdas that have a very specific function.

First off is “action”: This is what happens when our “results” object notices that our web service call has been completed. In my example I am connecting to an ASMX web service, and the return object (which becomes “action”) is typed IEvent. Using this, I can create a new variable “returnedResults” to which I assign the event args results, and from there process my returned array. This return is specific to my web service, and your results can be different.

Next lambda defined is “e”: this is simply “What do I do in the event of an error?”, and I have it writing out an error message to my textbox.

And the final part, “()” simply defines my completed action. This is simply “What do I do on completion?” In my case, all I wanted it to do was simply print out the final line to the textbox.

So now what do we do to make it make magic? Well, we simply call our service:

client.GetTopRevenueAsync();

And let the Observer do its thing. We defined “results” to listen for the GetTopRevenueCompleted event, and from there take the results and process as we have defined in our Subscribe call. Now we can build and run and see the fruits of our labor:

UI Results

And there you have it. That is everything needed to call a web service, process, and then display the results, all asynchronously from Silverlight.

Additional Reading:

Reactive Extensions: http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx

Lambda Expressions (XNA reference, but still applicable): http://nickgravelyn.com/2009/10/learning-lambda-expressions-for-xna-gs-developers/

Anonymous Delegates: http://geekswithblogs.net/joycsharp/archive/2008/02/15/simple-c-delegate-sample.aspx

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s