I’ve been seeing a lot of discussions lately on how to correctly use HttpClient in mobile apps, both UWP and / or Xamarin apps. In this post I’d like to share how I currently use HttpClient in my apps.
Read this first -> Disclaimer
This article discusses how I use the HttpClient class. If you use it in a different way or don’t agree with what I write here, feel free to start a constructive discussion in the comments. I’ll be happy to discuss your way of thinking vs mine and adjust the article where necessary.
To single-instance or to multi-instance
Back when I was getting into writing mobile apps (in the WP7 era) I started learning about REST services and how to call them from .NET code. I learned about HttpClient and quickly found out that it implemented IDisposable, so the logical step was the using keyword.
Turns out, not the best way to go at it. When you dispose an HttpClient instance, the connection to the server is closed.
When you do the next call to the server, with a new HttpClient instance, that connection is reopened. This causes delay in getting a response from the webservice. If a server really doesn’t want you to keep your connection open, it will inform us of that via a header and the HttpClient instance will quietly close the connection and reopen it the next time.
So, how do we create an easy to (re)use instance?
And to use this instance:
Use a base URL (and don’t even dare making it a magic string)
The HttpClient class has a base url property. As you might have figured out, that property is meant to contain the root url of your API. So if we modify our HttpClient a bit we get this
As for the magic strings remark, put all your string values into a constants class (or whatever you want to name it, as long as they’re all together). If you don’t understand the reasoning behind this, just try writing applications with string values in the code, you’ll find out soon enough
Use compression where possible
Since we’re mostly writing mobile applications we need to keep data usage in mind. We have no idea if our users will have an expensive data plan or unlimited data or if they’re on WIFI. This means that it’s our job as developers to keep the data usage as low as possible. The quickest win here is to compress the data from the server and decompress it on the device, this of course means that the server needs to support compression. If you yourself maintain the server, make sure that it is enabled (it’s enabled by default in Web API). Once that is enabled, we need to tell the HttpClient to enable decompression from either Deflate or Gzip formats. Enable decompression is done through an HttpClientHandler object that we can pass into the HttpClient constructor.
Another often overlooked way of limiting data usage is caching. You’d be surprised of the times users request the same data, if we cache the API result we can just fetch it from that cache again. Extra usability feature here is that we can actually show results when the device is offline. You can write your own caching framework if you want, or use one of the existing ones. I tend to switch between Q42 (they save cached data in JSON files) and Akavache (they save cached data in SQLite).
We often need to make API calls to secured services. To do this we need to go through some form of authorization / authentication flow where we get an access token from (a bearer token for example). That token needs to be passed in with every API call we make. Since we’re now using a single instance for our HttpClient, it would be nice to specify the token once and be done with it. This an easily be done by using the default headers. HttpClient contains a collection of headers that it will use with every call it makes. This is how you add a Bearer token for example:
HttpClient is an async library. This means that we usually use this in a method that returns either Task or Task<T>. This also means that if you don’t use ConfigureAwait(false) that you’ll create quite a lot of context switching. When you await an async method, and don’t specify ConfigureAwait(false), the method will do it’s thing on the thread pool and switch back to the caller’s context when finished. This is exactly the behavior that you want when you request a webresult and immediately put the data into a property that is bound against, since binding happens on the UI thread. But this is not what we want when we’re executing code in a library or in a service class, so that’s where we’ll use ConfigureAwait(false).
Let’s say, for example, that we have a method to fetch all resources as a JSON string. The correct way of using ConfigureAwait(false) would be:
The FetchData method doesn’t use ConfigureAwait(false) because it needs to return to the caller context. The caller context here is the UI thread. The property that the returned value is being set to will trigger a change notification, so we need to be on the UI thread.
The FetchAllResources method has two calls that are awaited, by not returning to caller context in that method we prevent two context switches to occur.
(Xamarin only) use ModernHttpClient
Xamarin allows us to write iOS and Android applications in C#. We can use the HttpClient for that but we'd be using an abstraction of the lowest common denominator of both platforms. If you use ModernHttpClient on those platforms instead, you will get the full networking stack of the respective platforms. (thanks for reminding me @Depechie)
In this post I discussed some techniques with using HttpClient to fetch data in mobile applications that I’ve picked up over the years. As I’ve mentioned in the disclaimer, this is what I’m doing today and what feels right to me. Feel free to let me know if you do things another way, if you can convince me that your way is better, I will have learned something and will update the post accordingly .