Friday, April 13, 2012

JSON POST with ASP .NET Web API

I have been struggling a bit with porting existing Json calls to the new ASP .NET Web API framework. I actually got the GET request working pretty quickly, but it were the POST (and DELETE en PUT) requests that were giving me headaches. Problem is the current brevity and lack of practical examples for the Web API framework. So here goes a short example of getting a Json POST up and running.

For these examples I used the Visual Studio 2011 beta version.

Let's first start with the GET request. What you need for this is the HttpClient class, which can be found in the System.Net.Http namespace. This class provides methods like GetAsync, PutAsync, DeleteAsync and PostAsync. The 'Async' extensions let you know that you can use the new async and await keywords to get this up and running. A GET requests with the HttpClient consists of only two lines of code.

var client = new HttpClient();
var response = await client.GetAsync("http://some_url/resource_name/resource_id");
response.EnsureSuccessStatusCode();

All of this is contained in a method that has the extra async keyword. I also added the EnsureSuccessStatusCode call to verify my call to the REST service didn't fail. If the call fails the EnsureSuccessStatusCode will throw an exception. So you can easily wrap this piece of code in a try catch block.

So, that was quite easy. The GET call should work immediately.

On to the POST call. I actually want to post an object to our REST service. The previous version of the code I was porting to the Web API used the RestSharp (performs REST calls) and NewtonSoft.Json  (serializes from and to Json) frameworks to perform REST calls (both are available via NuGet). I started out reusing only NewtonSoft.Json, since the HttpClient class removes the need for the RestSharp framework. But is turned out I couldn't get the serialized Json object send to the service in a acceptable format. The service kept giving me 400 Bad Request messages. So I was doing something wrong.

After some searching I found there are a couple of different content class types you can use when performing a PostAsync. I used StringContent up untill then, but I needed a ObjectContent. The HttpRequestMessage class can create one for you. Moreover, the Web API contains its own Json formatters, so the need for the NewtonSoft library became obsolete.

var anObject = new MyObjectType
{
    SomeProperty = "some value"
};

try
{
    var client = new HttpClient(); 
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var requestMessage = new HttpRequestMessage();
    var content = requestMessage.CreateContent<MyObjectType>(
        anObject,
        MediaTypeHeaderValue.Parse("application/json"),
        new MediaTypeFormatter[] { new JsonMediaTypeFormatter() },
        new FormatterSelector());

    var response = await client.PostAsync("http://some_url/resource_name", content);
    response.EnsureSuccessStatusCode();
}
catch (Exception exc)
{
    Console.WriteLine(exc.Message);
}


And there you have it, my first successful Json POST message.

3 comments:

  1. I don't seem to have the CreateContent method on requestMessage for posting data. I found a work-around though using webclient instead of httpclient.

    e.g.

    var wc = new System.Net.WebClient();
    wc.Headers.Add("Content-Type", "application/json");
    string results = wc.UploadString(URI, jsonStr);

    ReplyDelete
    Replies
    1. Just looked at the HttpRequestMessage class on MSDN, and indeed, there is no CreateContent method anymore (http://msdn.microsoft.com/en-us/library/system.net.http.httprequestmessage.aspx). The time I wrote this article was during the prerelease stages of WinRT, I am guessing they altered this class a bit. You might be able to now also use the Content property which has a get and set property.

      So thanks for pointing this out to me!

      Delete
  2. This comment has been removed by the author.

    ReplyDelete