piotrwalat.net

Building reactive XAML apps with ASP.NET SignalR and MVVM

2 comments

A great portion of mobile applications consumes data from HTTP services. This is usually achieved as a pull scenario in which apps initiate the data flow from the server. In many cases pushing data to the client is a more natural and potentially much better solution. In this blog post I will explore how ASP.NET SignalR can help XAML developers simplify the task of creating and consuming push services over HTTP. I will also show how to leverage MVVM pattern to create a user experience that is driven by incoming data. The example will be built for Windows Phone 8 and will use MVVM Light library.

What do I mean by ‘reactive app’?

MVVM and data-binding is by its very nature reactive. Any changes made to the view model should automatically propagate to the data-bound view. Thus being said, in many scenarios the true source of such change comes from the model that resides on remote server (eg. because a new entity has been added). Very often we want to be able to push this change across the wire so that it triggers relevant view updates. This is where SignalR can be leveraged – it can help us extend ‘reactivity’ beyond the network boundary.

In traditional scenarios apps that consume HTTP services will usually pull data from the server. This may happen on demand – e.g. when opening a new screen that presents a list of customers, or in regular intervals to check for any updates. There is nothing inherently bad with this approach and it suits a large number of cases. Sometimes, however constant polling for changes is undesired and can be sub optimal from performance perspective. Consider for example a financial app that should provide real-time like updates to the user (eg. commodity quotes) – in this case it feels natural to have data pushed to us from the service as new updates arrive.

From technical point of view SignalR may still use polling, but from logical point of view it creates an abstraction over the actual mechanism (be it long polling, web sockets or anything else) which makes our apps independent from it. This is a huge benefit.

Let’s see how we can use SignalR to write a simple ‘financial’ app.

Push service with ASP.NET SignalR

We will use SingalR hubs feature to create a push service. Create an Empty ASP.NET Web Application in Visual Studio and NuGet install or reference SignalR.

The example will operate on a simple model – a Quote class representing individual.. ‘quote’ (e.g. a currency exchange rate).

The hub will simply push quote updates to all interested parties.

For the sake of example we will generate some random data and push quote updates in regular intervals. This code is not that important, but may help if you want an example on how to generate sample data in SignalR projects.

That’s all we need on the server side. The most important line – hubContext.Clients.All.updateQuote(q); will push sample data to all hub clients.

Windows Phone 8 XAML application

As a next step let’s write a XAML client that will present this data. I will use a Windows Phone 8 app as an example, but Windows 8 (or WPF and Silverlight) will be conceptually similar.

Here is how we want it to look like. The quotes should update automatically, ideally with some kind of subtle animation.

Sample

Start by adding a new Windows Phone 8 XAML application and installing MVVM Light via NuGet. Instead of reusing the Quote class (by adding as link to WP8) we will create a separate model on the client side in order to implement INotifyPropertyChanged.

Now let’s think about how our view model(s) should receive update notifications from SignalR hub. We could open connection directly in the view model, get hub proxy instance and subscribe to updateQuote event. Something like that:

This would work and maybe is not that bad, but… it doesn’t seem that doing all this is something our view model should be concerned about. What it really cares about is data updates and connection state changes. How it happens and what is the underlying technology should be owned by another class.
Also if we had more than one view model using the same hub (e.g. list->detail scenario) we would need to duplicate the code and connections.

Let’s use MVVM Light’s messaging capabilities to propagate updates in a decoupled way (we could have also used an interface that exposes events).
This also means we will introduce more abstractions and complexity, so bear that in mind especially when working on small applications.

Now we need a class that will connect to SignalR hub and push the updates.

Please forgive me interface/class name ;)

The rationale behind providing IDispatcher interface is to be able to provide platform specific implementations (WP8, Windows 8, WPF, etc.). SignalR action handler can start from a non-UI thread and we need to be able to marshal execution to the UI thread.
Oh and remember – the WP8 emulator runs as a virtual machine, so make sure you don’t use localhost as the endpoint address.

Now we can instantiate this class (e.g. in Application object) and start the connection.

This will ensure that update events are being sent and can be consumed by the view model… which leads us to the view model itself.

It is quite simple and hopefully readable. MessengerInstance is a property provided by ViewModelBase and can be mocked for the sake of unit tests. Now, we need to write XAML view that will present data to the customer. For brevity I will only include most important parts here, you can have a look at full markup in the source code provided.

Because we want to have a strong order of elements on the list we use CollectionViewSource to do the sorting.

As you can see we didn’t have to write a single line of C# in the view’s code-behind. Sorting, updates and visual state transitions will all happen thanks to XAML.

Unfortunately I ran out of time to include a Windows 8 sample, but the code has been built in such a way that creating a Win8 application should be a simple task as we can reuse most parts (including view model, SignalR data provider).

ASP.NET SignalR bridges the gap between reactive world of MVVM and HTTP services that reside on a remote server.

The complete project is available on bitbucket and below you can see the end result. Of course the data is completely unrealistic :)

Written by Piotr Walat

May 8th, 2013 at 9:52 am