Portable Class Libraries + HttpClient: So Happy Together!
I was recently on Channel 9’s VS Toolbox talking about Xamarin and Portable Class Libraries where I showed of an expense taking application called My Expenses. This little app uses a portable class library and a SQLite database to store and track all of your expenses. I built out a full app for Android, iOS, and Windows Phone using this single PCL that housed 80%+ of all my code!
One feature in particular was a bit tricky which was that when the app starts up it calls out to a web service to pull down an update notification. I use HttpClient to easily call out with GetStringAsync and then parse the JSON with Json.NET. While this feature seems trivial, you have to remember that a PCL uses just a subset of the .NET Framework and unfortunately when you select Windows Phone System.Net.Http is no longer available. So here is how I went about adding in this functionality.
Create my PCL
From File -> New Project you will want to create a new Portable Class Library. Once you name it you can specify what platforms you want to support in this popup:Inside of Xamarin Studio it is very similar except that this popup doesn’t exist. You will have to select the Projects options and select the platforms you want to select after the project has been created, which is easy enough:
NuGet to the rescue!
One amazing thing about PCLs is the vast libraries that are available on NuGet. To get started you first need to get the latest NuGet manager for either Visual Studio or Xamarin Studio to consume these NuGets in your app. Once you have this we can simply right click on our References in the PCL and select Manager Nuget Packages. Once the window opens up simply search for Http Client to find the System.NetHttp Nuget:Awesome! Now we have HttpClient in our PCL and we can use it to make web request…. right?
Not so fast! Troubles in PCL Land
One thing to know about Portable class libraries is that they aren’t like other libraries out there and can bent and twisted to do crazy things. I wont get into the details of how PCLs exactly work as you can read Stephen Cleary’s post on them. I will say is that the NuGet package we just installed has a portable implementation of the HttpClient for platforms that don’t have them built in, such as Windows Phone. We can compile against this “contract” and implementation, but at build and deploy time the platform specific version will be used. This is important because both Xamarin.Android and Xamarin.iOS already have an implementation of System.Net.Http, so to make sure they get used we will want to add the references to those projects from our Add References popup.
On Windows Phone though it is a bit trickier as we need proper async/await support and a few platform specific HttpClient implementations. This is easy to remedy though as all we need to do is add the same NuGet to our Windows Phone projects! Check! Done!
Close to the finish line!
Now ideally at this point we should just be “done” and when I was building out my demo project I thought I was until I ran my app on an iOS device. As you may know that iOS apps are all ahead of time compiled (AOT), which means that if any of your code needs to JIT it simply will not work. For some reason at compile time the facades don’t kick in properly and it tries to use the NuGet version of System.Net.Http which has some specific functionality for older platforms. We simply do not need this, so let’s show MSBuild who the boss is and redirect it to use our DLL that we have already. All you need to do is create a new app.config file in your Android and iOS project. We will then tell the app.config to forcefully use our DLL that we included with this config:
Now we are back on track and everything works properly!
Super charge HttpClient!
Now we could just stop there, but what fun would that be? HttpClient is great, but we can actually improve upon it with using platform specific networking libraries. This is where Paul Betts’ ModernHttpClient Component comes in. He describes it as:
This library brings the latest platform-specific networking libraries to Xamarin applications via a custom HttpClient handler. Write your app using System.Net.Http, but drop this library in and it will go drastically faster. This is made possible by two native libraries:
On iOS, AFNetworking 1.3.3
On Android, via OkHttp 1.2.1
So this is fantastic because we don’t actually have to change any of our HttpClient code except for when we create a new one where we can pass in a HttpMessageHandler. So let’s get this puppy installed and super charged!
First off is to install the ModernHttpClient Component in both Android and iOS projects. You can do this by right clicking the components folder and selecting Get More Components. Once the component store comes up simply search for ModernHttpClient and add it to your project:
Alright, now it is time for some platform specific code as we will need a way to get the AFNetworkHandler or OKHttpNetworkHandler in our PCL. To do this we will need a little bit of platform abstraction, so I will create an interface that I will implement on both Android and iOS. The interface is simple as it has one simple getter for a HttpMessageHandler and then simply create the specific handler on each platform:
I have my own IoC container that I use to register these classes in each application’s start up code. Then whenever I need to actually create a new HttpClient I use this simple method to get the correct HttpMessageHandler to pass in to HttpClient’s constructor:
There you have it! HttpClient everywhere and super charged on both Android and iOS with ModernHttpClient. If you happen to be using MvvmCross check out my good friend Tomasz’s GitHub for a nice plugin for ModernHttpClient.
*Note: System.Net.Http relies on Microsoft BLC Build Components NuGet and this is recommended to add to all of your projects that reference the PCL.