6

I'm playing a little bit with this new technology in .net 4.5, I would like to check the code for this call and how should I control the errors or the response of my async call. The call is working perfectly, I need full control of possible errors returned from my service.

this is my code:

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;

namespace TwitterClientMVC.Controllers
{
    public class Tweets
    {
        public Tweet[] results;
    }

    public class Tweet
    {
        [JsonProperty("from_user")]
        public string UserName { get; set; }

        [JsonProperty("text")]
        public string TweetText { get; set; }
    }
}

public async Task<ActionResult> Index()
{                                             
    Tweets model = null;

    HttpClient client = new HttpClient();

    HttpResponseMessage response = await client.GetAsync("http://mywebapiservice");

    response.EnsureSuccessStatusCode();

    model = JsonConvert.DeserializeObject<Tweets>(response.Content.ReadAsStringAsync().Result);

    return View(model.results);            
}

Is this the better way to do it? or I'm missing something? Thanks

I refactor it, is this method async as well?

public async Task<ActionResult> Index() 
    {
        Tweets model = null;
        using (HttpClient httpclient = new HttpClient())
        {
            model = JsonConvert.DeserializeObject<Tweets>(
                await httpclient.GetStringAsync("http://search.twitter.com/search.json?q=pluralsight")
            );
        }
        return View(model.results);
    }
rgx71
  • 817
  • 6
  • 21
  • 32

1 Answers1

7

Is this the better way to do it?

The response.EnsureSuccessStatusCode(); will throw an exception if the status code returned by your remote service is different than 2xx. So you might want to use the IsSuccessStatusCode property instead if you want to handle the error yourself:

public async Task<ActionResult> Index()
{                                             
    using (HttpClient client = new HttpClient())
    {
        var response = await client.GetAsync("http://mywebapiservice");

        string content = await response.Content.ReadAsStringAsync();
        if (response.IsSuccessStatusCode)
        {
            var model = JsonConvert.DeserializeObject<Tweets>(content);
            return View(model.results);            
        }

        // an error occurred => here you could log the content returned by the remote server
        return Content("An error occurred: " + content);
    }
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • sorry, I have another question, if this method is really async, how could I be sure that at the moment of DeserializeObject, the web service has finished? – rgx71 Mar 07 '13 at 16:49
  • 1
    I have updated my answer. You should use `string content = await response.Content.ReadAsStringAsync();`. This will ensure that by the time the execution reaches the `DeserializeObject` call, the client has finished executing the request and reading the result. My original code was synchronous and blocking because I was calling the `.Result` property on the content that was read. This means that it was also guaranteed that the execution has finished but it was synchronous. It's better to use `await` which is true asynchronous processing. – Darin Dimitrov Mar 07 '13 at 16:51
  • thanks, so we need to use it in th GetAsync call and also when we are using ReadAsStringAsync. What about IsSuccessStatusCode? at that moment, are we sure the call was finished? – rgx71 Mar 07 '13 at 17:11
  • Yes, you should use it in both calls, and yes it is guaranteed that by the time you hit the `IsSuccessStatusCode` the call will have completed. – Darin Dimitrov Mar 07 '13 at 17:12
  • I did a modification in my first post with a new method, is this method also async? – rgx71 Mar 08 '13 at 14:39