Translate

Monday, November 4, 2013

Avoiding a pitfall wrapping HttpClient for asynchronous tasks.

Recently, I wanted to wrap client calls to a REST service in order to insert header or other information into each call and provide the developer with an easy client API to access a service. I wanted and GET or POST operation to return a task with the HttpResponseMessage class just like making a direct call to HttpClient. I made this mistake at first:

protected Task PostAsync(Uri requestUri, T value)
{
  using (HttpClient client = new HttpClient())
  {
    // Right here I inserted additional stuff into the HTTP header such as authentication information.

    if (useToken)
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);

    return client.PostAsJsonAsync(requestUri.AbsoluteUri, value);
  }
}

None of my calls were reaching the server, and upon inspection on the client side I would receive an exception telling me that 'the request was aborted'. Duh, obvious when thinking about it, the HttpClient is disposed upon returning and therefore 'the request was aborted' before the task is kicked off and returned. A very easy fix is to kick off a task myself:

protected Task PostAsync(Uri requestUri, T value, bool useToken = true)
{
  return new TaskFactory().StartNew(() =>
  {
    using (HttpClient client = new HttpClient())
    {
      // Right here I inserted additional stuff into the HTTP header such as authentication information.

      if (useToken)
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);

      return client.PostAsJsonAsync(requestUri.AbsoluteUri, value).Result;
    }
  });
}

No comments:

Post a Comment

Codementor

Ryan Kuhn

★★★★★

Expertise