Web Service Resilience

Currently my Weather app is providing data from the Met Office Data Point web service and everything seems to work well, until there is no internet connectivity. For mobile applications this is a crucial aspect for web services which need to be built into our applications. It is important that we can check if we have connectivity to the internet and take steps accordingly. One thing I want to achieve is to cache any data so that it can be shown first the next time I try to connect. This gives a perceived performance improvement because data can be displayed whilst trying to connect to get updates. This all seems like it could be quite a lot of hard work to achieve with Xamarin Forms but it is actually very simple with the help of a couple of plugins.

Connectivity Plugin

This is a simple cross platform plugin to check the connection status of a mobile device and provide information about connection types, bandwidths etc. It is written by James Montemago so it is bound to be good stuff. Simply install this via NuGet from either Visual or Xamarin Studio. Make sure that you add this to both your PCL and Target platform projects. Also on Android make sure that you add permissions for ACCESS_NETWORK_STATE and ACCESS_WIFI_STATE in your project preferences.

The usage is very simple. To check if the device is connected just call

CrossConnectivity.Current.IsConnected.

This however will return true if you are connected to Wi-Fi but don’t have an internet connection, so you need to also call CrossConnectivity.Current.IsRemoteReachable passing in a valid web URL (without http or www), for example google.com. This is also asynchronous so you should await this call. Combine both these calls to correctly check for a connection like this:

public async Task<bool> IsConnected()
{
    return CrossConnectivity.Current.IsConnected &&
           await CrossConnectivity.Current.IsRemoteReachable("google.com");
}

Akavache

I also want to be able to cache any previous data and display this whilst I attempt and retrieve any updated data. Akavache, written by Paul Betts, provides an excellent data persistence library based on SQLLite3. Matthew Soucoup provides us with a great article on Akavache here. Also checkout this post here on installing Akavache as you may have to update some packages for Windows Phone projects.

What’s really great is the ability to return cached data, if there is any, and then go and fetch data from a web service and store that as the cached data for next time. You would think this would take quite a lot of work to achieve, but Paul has utilised some Rx (Reactive Extensions) goodness and provided a method named GetAndFetchLatest, which we can subscribe to get an observable stream of both the cached data and the updated data.

Combine this will Cross Connectivity and we can provide a resilient web service call that will return any cached data first, if there is any, check for an internet connection then go a fetch data if we are connected and return that as well as caching it for next time. If there is no connection then simply return and just display the cached data.

public IObservable<ForecastReport> GetAreaForecast(int id)
{
    return BlobCache.LocalMachine.GetAndFetchLatest("AreaForecast" + id,
        async () =>
        {
            if (!await IsConnected()) return null;
            return await GetAreaForecastAsync(id);
        }, null, null);
}

And then we can subscribe to the observable like this and update our view model as we receive them.

IsBusy = true;
service.GetAreaForecast(id)
    .Subscribe(result => InitialiseForecast(result), HandleError,
        () => IsBusy = false);

All very clever stuff I’m sure you’ll agree.

There are a number of other great libraries out there for Xamarin Forms to help with network resilience. It’s worth checking out the excellent ‘Resilient network services with mobile Xamarin apps’ by Rob Gibbens for more details.

2 thoughts on “Web Service Resilience

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