Using async/await, System.Net.Http.HttpClient, and MvvmCross in WP8, Xamarin.Android, and Xamarin.iOS

UPDATE: This post was written using Xamarin.Android 4.8 and Xamarin.iOS 6.4 business editions in Visual Studio 2012.

Alright everyone, raise your hand if you typically gravitate towards using the latest and greatest tools, libraries, and patterns in the applications you develop. Well, the newest hotness in the world of Xamarin.Android and Xamarin.iOS cross-platform development is the async/await and System.Net.Http.HttpClient support they added in the recent release.

If you’re developing either an Android or iOS application or you’re not using PCLs to share code across platforms then this post probably isn’t for you. If however, you’re like me and targeting multiple platforms (i.e. Windows Phone, Android, iOS) and using a PCL library such as MvvmCross to maximize code reuse, then chances are you’ve spent some hours in NuGet/PCL hell banging your head trying to get async/await working across all platforms.

I’m hoping this post can help others avoid the pain and misery of getting async/await and HttpClient working in their cross-platform application that makes use of PCLs like MvvmCross. This is likely one of many possible configurations that work – it just happened to be the first configuration that worked for me and it wasn’t terribly offensive. Don’t be scared off by the 23 steps listed below – it not really that bad…I’m starting a solution from scratch and being as explicit as possible. So, without further ado, enjoy!

  1. Create a Portable Class Library project named CrossPlatform.AsyncAwaitHttpClient.Core.Pcl. Target Frameworks: .NET Framework 4.5, Silverlight 4 and higher, Windows Phone 7.5 and higher, .NET for Windows Store Apps, Mono for Android, MonoTouch (if you don’t have Mono for Android and MonoTouch listed as Target Frameworks, read this post: Cross-Platform, WinRT, MonoDroid, MonoTouch, MonoMac,  PCLs and VS2012). Delete Class1.cs after the project is created.
  2. Edit project properties for the CrossPlatform.AsyncAwaitHttpClient.Core.Pcl project you just created and remove “.Pcl” from the Assembly name and Default namespace. Save your changes.
  3. Install the MvvmCross NuGet package in CrossPlatform.AsyncAwaitHttpClient.Core.Pcl.
  4. Create a new .NET Framework 4.5 Class Library project named CrossPlatform.AsyncAwaitHttpClient.Core.
  5. Install the MvvmCross NuGet package in CrossPlatform.AsyncAwaitHttpClient.Core. Delete all files in the project except packages.config.
  6. Drag the ViewModels folder and App.cs from CrossPlatform.AsyncAwaitHttpClient.Core.Pcl to CrossPlatform.AsyncAwaitHttpClient.Core.
  7. Add reference to System.Net.Http assembly to CrossPlatform.AsyncAwaitHttpClient.Core.
  8. Optional: Remove CrossPlatform.AsyncAwaitHttpClient.Core.Pcl project from solution – we just needed it to get App.cs and FirstViewModel.cs files since the MvvmCross NuGet package thinks our plain .NET Framework 4.5 class library is a WPF application.
  9. If you’re targeting the Windows Phone platform in addition to Android and/or iOS, follow steps 10 – 14 below otherwise skip to 15.
  10. Create a new Windows Phone Class Library named CrossPlatform.AsyncAwaitHttpClient.Core.Phone.
  11. Edit project properties for the CrossPlatform.AsyncAwaitHttpClient.Core.Phone project you just created and remove “.Phone” from the Assembly name and Default namespace. Save your changes.
  12. Install the MvvmCross NuGet package in CrossPlatform.AsyncAwaitHttpClient.Core.Phone. Delete all files added to project except packages.config.
  13. Install the Microsoft.Bcl.Async and Microsoft.Net.Http NuGet packages in CrossPlatform.AsyncAwaitHttpClient.Core.Phone.
  14. Create a ViewModels folder in CrossPlatform.AsyncAwaitHttpClient.Core.Phone. Add “Existing Item…” for App.cs and FirstViewModel.cs found in CrossPlatform.AsyncAwaitHttpClient.Core, however, select Add as Link instead of Add.
  15. Create your client projects for Windows Phone, Android, iOS (i.e. CrossPlatform.AsyncAwaitHttpClient.Phone, CrossPlatform.AsyncAwaitHttpClient.Droid, CrossPlatform.AsyncAwaitHttpClient.Touch).
  16. Install the MvvmCross NuGet package to each project created in step 14.
  17. Follow the instructions found in the ToDo-MvvmCross folder of each of your client projects to get them setup with MvvmCross. In the Droid and Touch client projects, add a reference to the CrossPlatform.AsyncAwaitHttpClient.Core project as your MvvmCross Core. Windows Phone projects should add a reference to the CrossPlatform.AsyncAwaitHttpClient.Core.Phone project instead.
  18. Install the Microsoft.Bcl.Async and Microsoft.Net.Http NuGet packages in your Windows Phone client project.
  19. Add a reference to the System.Net.Http assembly (C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v1.0\System.Net.Http.dll) to your Android client project.
  20. Add a reference to the System.Net.Http assembly (C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoTouch\v4.0\System.Net.Http.dll) to your iOS client project.
  21. Update the line in the LinkerPleaseInclude.cs of your iOS project from:
    imageView.Image = new UIImage(imageView.Image);

    to:

    imageView.Image = new UIImage(imageView.Handle);
  22. Update your FirstViewModel.cs to make a web request using the HttpClient (see example on the Xamarin Developer Center for an example: Async Support Overview).
  23. Voila! No more head banging.

I hope this walkthrough wasn’t too terrible. I’d be interested in hearing from you if you’ve found a different way of making this all work. What’s interesting is that I first started down this rabbit hole by installing the Microsoft.Bcl.Async and Microsoft.Net.Http NuGet packages across the board – and it worked in Windows Phone and Android but not iOS. Anyway, like I said, let’s compare notes if you have a different approach that works.

You can download the sample solutions here: CrossPlatform.AsyncAwaitHttpClient.zip

Advertisements

8 responses to “Using async/await, System.Net.Http.HttpClient, and MvvmCross in WP8, Xamarin.Android, and Xamarin.iOS

  1. Pingback: Xamarin Link Roundup – 15 Aug 2013 | Well Technically…·

  2. Thanks. It does work.
    But can you please explain why, I am a bit confused.
    How is it possible for the mobile apps to run fine when they have as reference ‘CrossPlatform.AsyncAwaitHttpClient.Core’ which is a WPF class library.

    • Hey Andrei,

      I was a little confused myself until I found the Xamarin release notes which indicate that Xamarin.Android 4.8+ and Xamarin.iOS 6.4+ now use Mono 3. The async/await functionality in Mono 3 comes from the fact that the Mono 3 class libraries are based on the .NET 4.5 profile – really awesome stuff!

      I spent a ton of time trying to get the Microsoft.Bcl.Async and Microsoft.Net.Http libraries working in Android and iOS but it turns out I just needed to use a plain old .NET 4.5 class library. WPF enters the scene merely because the MvvmCross NuGet package isn’t intelligent enough to recognize that the .NET 4.5 project is your Core project and not an app project. I’m guessing if I would have just installed the MvvmCross.HotTuna.CrossCore NuGet package it would eliminate the need to delete all the WPF stuff from the project.

      Hope that helps!
      Ryan

      • ran into a new problem… I succesfully manage to add a reference from my core to my droid project, however I get the warning: “The project cannot be referenced. The referenced project is targeted to a different framework family”

        And even worse, when i try to make the Windows 8 version, the reference won’t even make it.

        How can i solve both things?

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