piotrwalat.net

Consuming ASP.NET Web API services in Windows 8 C# XAML apps

13 comments

If you are writing Windows 8 app, chances are that you will need to communicate with some sort of service to retrieve or send data.
In this blog post I will show how to set up a basic CRUD ASP.NET Web API REST like service and how to consume that service from a C# Windows XAML 8 app (‘modern style’ aka ‘M**** style’ that is :)). I will also show how to build a simple user interface in XAML powered by data retrieved from our service and how to leverage MVVM pattern to make the code a little bit more maintainable.

Let’s start off by creating a simple model for our example.

We also want a way to persist our objects, instead of using a database I will just store them in memory (using thread safe collections introduced in .NET 4) and use a repository pattern to abstract actual persistence mechanism.

CRUD service in Web API

The next step is to create a simple Web API service that will provide basic CRUD operations.
HTTP/1.1 protocol defines a set of common methods that map to these operations in a following way:

  • GET  /api/expenses – get a list of all expenses
  • GET  /api/expenses/id – get expense by id
  • POST  /api/expenses – create a new expense
  • PUT  /api/expenses/id – update an expense
  • DELETE  /api/expenses/id – delete an expense

If you have been implementing REST services before it may seem to be quite obvious.
The tricky part is (at least in my opinion) to make our service as HTTP compliant as possible by returning appropriate responses and status codes.

You can find HTTP/1.1 spec document here (*cough*@frystyk is a co-author of this document *cough*). For example a section on POST method states that for resources that can be identified by a URI “the response SHOULD be 201 (Created) and contain an entity which describes the status of the request (…) and [contain] a Location header”. Because expenses can be identified by a URL /api/expenses/id (it is a resource),  ideally we should follow this specification. Fortunately HTTP is a first class citizen in Web API and tasks like setting Location header in response are simple. In real world scenario we would also get rid of an unbounded Get() method and use paging or other result limiting mechanism.

Windows 8 app

For the sake of demonstration I am keeping the application very simple (and ugly unfortunately). It will consist of one screen and will be capable of:

  • getting and displaying a list of all expenses,
  • adding a new expense (with randomly generated properties),
  • deleting selected expense,
  • modifying selected expense.

All these operations will call our new shiny Web API HTTP service to retrieve and manipulate data.

Win 8 Expenses app

 

Communicating with Web API

To consume HTTP service from Windows 8 app we can use an instance of HttpClient or HttpWebRequest class (the latter provides a little bit more features) . It’s worth mentioning that out of the box, ASP.NET Web API supports both xml and json as media types for messages being exchanged with clients (you can use accept header to specify which one you want to use). Windows 8 also supports serialization/deserialization for both formats (through XmlSerializer and DataContractJsonSerializer classes respectively), without a need for external libraries. In this app I am going to use HttpClient and json as a message format.

But where should we put the logic to actually communicate with our server and serialize/deserialize entities?
The simplest solution would be to place it directly in code behind in event handlers associated with particular user actions. Even though suitable for such a simple demo app, this approach would backfire on us in more complex scenarios (imagine for example that we wanted to add authorization to our service in the future – we would need update code in many places). Because of this lets abstract actual data manipulation (and communication) logic.

This interface provides basic data manipulation operations, its implementation that uses Json (DataContractJsonSerializer)  and HTTP to communicate with Web API service will look like this:

The main benefit of DataContractJsonSerializer  is that it is being provided by the platform (no concerns about using 3rd party library). On the other hand it requires a little bit of code to set up and its api is a somewhat clunky.

Here is IExpenseService implementation that uses Json.NET, which is a very popular Json serialization library for .NET. If you want to use it the easiest way is to get a NuGet package.

I like it better :).

Please note that we are leveraging async/await support provided by the platform. It will help us reduce code complexity later on.

XAML

IExpenseService  enables us to communicate with our Web API service, but we need to call this logic somewhere and we obviously need UI as well. As I said before, to keep things simple lets use one page only.

Please note that I am using MVVM pattern, but if you dont feel comfortable with it you can just stick IExpenseService calls in code-behind. Expense list will be displayed by ListView. We use bottom AppBar to provide user with buttons and there is a simple activity indicator (ProgressRing) which will be displayed while we are retrieving data from the server.

View model

We also need to create a view model that the page will bind to and that will encapsulate view related logic.

I have removed less important code to make it smaller and easier to read. I am also generating random data instead of providing user editable forms.

There are two patterns worth mentioning here. First of all we are using commands (RelayCommand is an ICommand implementation and you can find it in source code) to react to user actions. For delete and update operations we provide canExecute predicate that determines whether a command can be executed or not. This is used to disable buttons when no item is selected.

The other pattern is the use of IsBusy property to indicate that view model is ‘busy’ – in our scenario that we are in progress of sending or retrieving data from server. Thanks to async/await support in .NET 4.5 and C# Windows 8 apps we don’t have to worry about thread marshaling and the code looks as if it was synchronous.

You can download or view full source code (for both services and client app) on bitbucket (alternatively zip archive here).

Written by Piotr Walat

September 10th, 2012 at 2:02 am

  • Pingback: Dew Drop – September 10, 2012 (#1,397) | Alvin Ashcraft's Morning Dew

  • http://www.bizcoder.com Darrel Miller

    Can I suggest that you move the HttpClient instance up into a field of the service.  When you dispose a HttpClient, by default it will cause the HTTP connection to be closed.  This means every request will pay the price of re-establishing the connection.

    • http://www.piotrwalat.net/ Piotr Walat

      Hi Darrel,
      Yeah that is true. The problem with having HttpClient as an instance field is that we lose thread safety in ExpenseService (because HttpClient instance methods are not marked as thread safe). Moreover it would mean service has to implement IDisposable (which maybe is not a bad thing, but complicates its api a little bit).

      I am actually curious to test the performance hit (especially in the context of mobile devices and battery life) of connection re-establishing.

      • http://www.bizcoder.com Darrel Miller

        My understand is that the HttpClient instance methods are thread safe.  I certainly use them across threads.  In the very early days there were some issues accessing the HttpHeader objects across threads but they seem to have been resolved. 
        As far as the disposing goes, I would consider injecting a HttpClient instance into the ExpenseService and dealing with the cleanup as part of your Model teardown. 
        The other advantage of having a long living HttpClient is that it makes it easier to set default headers like auth headers and also, if you start providing an alternative HttpMessageHandler in the constructor, that’s a pain to have to setup everywhere.

        • http://www.piotrwalat.net/ Piotr Walat

          Hmm MSDN (http://msdn.microsoft.com/en-us/library/system.net.http.httpclient.aspx)
          states that “instance members are not guaranteed to be thread safe.”.
          Very likely that I miss something, but I had a brief look at HttpClient sources and it didn’t seem to be obviously thread-safe.
          This is the concern that prevented me from making HttpClient an instance field, other things are easy to tackle (IDisposable can be taken care of by container/cleanup as you mentioned)

          Thanks for constructive input.

          • http://www.bizcoder.com Darrel Miller

            I just checked with a dev on the networking team and he said the MSDN comment is a standard disclaimer and

            “HttpClient and HttpMessageHandlers are
            hardened to work on multiple threads. 
            HttpRequestMessage, HttpResponseMessage, HttpContent, etc. are not.  E.g. It is safe to send multiple requests
            simultaneously, but it is not safe to manipulate a single request simultaneously
            on multiple threads.”

  • Pingback: Interesting .NET Links - September 10 , 2012 | TechBlog

  • Pingback: Consuming Asp.net Web API from Win 8 XAML apps | Chris May · { .Net Development;}

  • Taobaostopru
  • Pingback: WinRT. Primeros pasos con ASP.NET WebAPI. | Javier Suárez Ruiz | Blog

  • http://profile.yahoo.com/BKHSVGASI2RUFI5SHR7Z2YHQ7E edmilson

    Excelent Post!
    easy to understand and clean. I´d like to see one exemplo with  regular data (strings and so on)  and  also photos and  Videos, been consuming  from the WEB API, as the new UI Modern Style has  this bigger visual with  Photos I´d  like to know how to  put  it  in my APP

  • http://myleschambers.webstarts.com/ HerrodFrye

    Hold yourself responsible for a higher standard than anyone else expects of you. Never excuse yourself. My understand is that the HttpClient instance methods are thread safe. I certainly use them across threads.  In the very early days there were some issues accessing the HttpHeader objects across threads but they seem to have been resolved.  

  • Pingback: qujck