Using Microsoft Web API from a Windows and WinRT Client Application

Posted by: Sumit Maitra , on 3/6/2012, in Category WinRT
Views: 108350
Abstract: In this post, we will see how we can create a Windows and WinRT application that connects to Web APIs released with ASP.NET MVC 4 and can retrieve and submit information.

Recently I posted on how the new Web API framework released with MVC4 Beta was designed to enable services over plain HTTP using HTTP verbs. So any Web API we create and expose for our application, is easily accessible from any client that can do an HTTP Post.

In this post, we will see how we can create a Windows and WinRT application that connects to the Web APIs we exposed in our previous post and can retrieve and submit information.

Quick Recap

We have a (Blogging) application that has one Entity BlogPost. It’s built on MVC4 and uses a Repository to do serialization and deserialization. I used the standard Razor views and MVC Controllers for view and routing.

Now this app has become a runaway success and everyone wants to access it and create various clients for it.

 

We were already aware of our impending success, so we exposed our Get (to get all blog posts), Put (to update blog posts) and Post (to create new blog posts) using methods on the DevController using Web API. This means on the server side we have no more work to do other than telling people that they have to use the following url.

http://<ourbloglocation>/api/dev

Note: To run this example successfully, download the MVC4 app and have it running in the background.

Building a Client Application for Web API

Given the above URL, we will now put ourselves in the shoes of the developers who want to build a client application. What other information do they need?

If we hit the above URL, IE will try to download a file. If you save the file and open it in a text editor, you will see the following

image

As we see, we have a JSON string that represents an array with two objects. Each object has three keys Id, Post and Title. With this information at hand, let’s try to build a client application that can retrieve the posts, update them and add new ones.

A WinForms Client Application

Let’s quickly build a WinForms application that will connect to our Web API service.

Step 1: Start a new WinForms project

Step 2: Add a new Folder called ViewModel and add a class ViewPost.cs. This will be the class that encapsulates the data on the client side. It has three properties named according to the JSON object above.

viewpost-cs

Step 3: Add reference to the following dlls, all of which are installed as a part of the MVC4 Beta installation.

  1. System.Json
  2. System.Net.Http
  3. System.Net.Http.Formatting

Step 4: To the default Form1.cs add a Label, a TextBox, a Button, a DataGridView, a MenuStrip and a Timer. The layout looks as follows

blog-writer-layout

Step 5: Assign a click handler for the button and add the following code to it

get-all-posts

The event handler calls the GetAllPosts method. Let us look at this method closely

  1. We first initialize the HttpClient.
  2. Enable the timer (we will see the reason shortly).
  3. On the client we call the GetAsync method and pass the text in textbox1. This basically is the URL of our service (e.g. http://localhost:1100/api/dev). We are calling the Async method so this is a non-blocking call. As a result if we try to bind the grid to our data source (List<ViewPost> _posts) immediately after this call, it will not have any data. So we have designed a crude polling system using the timer, which will tick every half a second to see if the _posts has any data, and if it does, it binds to the Grid. The code for the time tick event is as follows

    timer-tick-handler          
  4. Looking further into the Async call we see, we have put in an anonymous method to be chained once the Async call returns. Code called by ContinueWith executes when the Async task completes.
  5. We see requestTask is populated once our Async call completes.
  • We extract the HttpResponseMessage from the task
  • Next we call EnsureSuccessStateCode(). This method will throw an exception if the HTTP response code does not match a success code.
  • Next we read the ‘Content’ of the response message. The System.Net.HttpFormatting provide the ReadAsAsync<JsonArray> extension. As we can see this is also an Async call that passes on the Task object to our anonymous method as the readtask parameter.
  • The first for loop will be executed as many times as the number of posts available. For example, for the following data it will execute twice

image

  • Then inner foreach enumerates through each property in the JSON object. So for the each object above it will execute thrice, each time updating one property.
  • Once the object is updated, the ViewPost is added to our data source. At this point if we run this application we should see the same posts that are in the Web Application, show up in the Grid.

blog-writer-index

  • This demonstrates how to use the HTTP GET verb. Let us continue and do the PUT and POST implementations

Step 6: Add a new Form to the project and call it BlogWriter. Add a label, two TextBoxes for Title and Post and two buttons for Save and Cancel. The layout looks as follows

blog-editor-layout

Step 7: Add a new Constructor for this class such that the ViewPost object that it is going to get edited is injected in the constructor itself. Along with it, the url of our Web API is also passed

blog-editor-constructor

Step 8: Add a click handler for the Save button. On click we check if the post that is getting edited has a non-zero Id. If it does, that means it’s an update operation and we need to use HTTP PUT. If Id is zero, means it’s a new entry and we should use HTTP POST. The entire code is as follows

http-post-put

1. The SetupClientContent method

  • Is responsible for setting up the HttpRequestMessage. We setup the ObjectContent to be of type ViewPost and assign the post object after updating it with latest values from the UI.
  • It is extremely important to setup the Header properly, and since we will be posting JSON we setup the ‘Content-Type’ as ‘application/json’.
  • This method is used by both the Save and the Create Methods

2. Save method

  • Creates the HttpClient object, initializes the content and calls the PutAsync.
  • On task completion verifies the Submit was successful by calling EnsureSuccessStatusCode().
  • Sets the DialogResult to OK so that the dialog closes itself.

3. Create method

  • Create the HttpClient object, initializes the content and calls the PostAsync method.
  • On task completion verifies the Submit was successful by calling EnsureSuccessStatusCode().
  • Sets the DialogResult to OK so that the dialog closes itself.

Step 9: Hooking up the Post Editor to the main app.

  1. Add a cell double click even handler to the dataGridView and initiate the BlogEditor using the ViewPost at that cell index.
  2. Add a Click event handler for the File->New menu item and initiate the BlogEditor using a new ViewPost object.
  3. In both cases if DialogResult returned is OK call the GetAllPosts() method to refresh the post list.

    launch-blog-editor-dialog
  4. We are now ready to run the application. Run it and provide the URL and hit Go, to bring up the current list of Posts.
  5. Double click on an existing Post, to bring up the Editor. Make some changes and Hit Save.
  6. Watch as the Data gets refreshed in the list.

In Conclusion

We saw how WebAPI delivers on the promise of services over HTTP. Prior to WebAPI, we would have to do this through Web Services that involved at the very least reference and configuration of the Web Service, proxies and stubs.

In case of WebAPI also, we needed the ‘reference’ URL and a sample of the data type but the contract is much more informal as in we are free to use our POCOs on the client side as long as they get mingled into the same JSON at the time of POST/PUT.

This make WebAPI a very attractive framework to use when we want services of our web application exposed over HTTP.

Exercise – Develop a WinRT application using the same WebAPI

I could have built this client app in WinRT as well. I leave that as an exercise for you dear reader.

The code for a WinRT application will be very similar except that the HttpClient is defined in a System.Net.Http namespace; the JSON object is defined in Windows.Data.Json namespace.

In WinRT we don’t have a JSON DataContractSerializer implemented so instead of ReadAsync<JsonArray> you have to use ReadAsStringAsync<string> and the rebuild the JSON object from the string that is returned. The following is the WinRT version of the code

winRT-code

That’s it for now. Have fun with Web API.

The entire source code of this article can be downloaded over here

Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles
Sumit is a .NET consultant and has been working on Microsoft Technologies since his college days. He edits, he codes and he manages content when at work. C# is his first love, but he is often seen flirting with Java and Objective C. You can follow him on twitter at @sumitkm or email him at sumitkm [at] gmail


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by Roberto on Tuesday, March 13, 2012 6:49 PM
Excellent article. I'm using to build an application in winforms. However I am struggling to perform authentication. How can I authenticate HTTP requests without the service redirects to the login page? The HTTP client is in the same namespace of my mvc application, used for monitoring and adminstration of the content sent to the service.
Comment posted by Sumit on Wednesday, March 14, 2012 12:10 AM
@Roberto Thanks, glad you liked it. Check out a slightly old article by Phil Haack at http://haacked.com/archive/2011/10/19/implementing-an-authorization-attribute-for-wcf-web-api.aspx

WCF WebAPI is the precursor to the current WebAPI release, so some of the calls may have been moved around. Let me know if it works for you, else I'll have to speed up my plans for the followup post with Authorization using WebAPI :-)
Comment posted by Roberto on Wednesday, March 14, 2012 1:41 PM
Hi, Sumit.
I had read the article by Phil, but as it was completely addressed to wcf web api I could not use it. There are other articles on the same subject, with similar solutions (http://cacheandquery.com/blog/2011/03/customizing-asp-net-mvc-basic-authentication, http://codebetter.com/howarddierking/ 2011/10/11/oauth-2-0-in-web-api, etc.) but neither is it simply and with the client being in a non-web application. I will await your post about authentication to enhance security of our application.
Comment posted by kuldeep butani on Friday, August 10, 2012 9:32 AM
hello sir,
I am using mvc4 webapi application and i had made a application which i am use with help of fiddler means crud operations now i had implement a client page in windows application like yours application now please now me how we use the crud operations.
Comment posted by James Hancock (Tradepoint360.com) on Friday, October 26, 2012 8:20 AM
FYI, people should NOT USE THIS CODE.

There are massive cross threading issues in it. While you can theoretically read a value from a control in another thread without problems you MUST use invoke on all sets in any async method.

That means everything that has a control to the left of the = sign must be wrapped in an invoke command no matter if you're using WinForms, WPF or even Windows 8 Runtime.

timer.enabled must be invoked, so too must all of the textbox results etc.

If you fail to do this you'll get random cross thread exceptions that are almost impossible to track down.

Always do it this way:

thisForm.Invoke(new MethodInvoker(delegate() {
   //Your code setting controls.
}));

Anything else will blow up in your face.
Comment posted by joe on Wednesday, May 1, 2013 8:39 AM
Can you do an article on this subject doing multiple file uploads?
Comment posted by Hassan on Sunday, January 5, 2014 7:15 AM
great article. I am looking for something in MVC 5 or mvc 4 similar to this article http://msdn.microsoft.com/en-us/magazine/cc163821.aspx where a windows service calls a web service / web api all in the same application. Do you of any article that does that?

Thank you

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel