jaymedavis/stripe.net — pull request #133 by baronfel (2014-01-18 20:31:08+00:00)
Title: Async await http client

Ok, there's a lot involved with making these interactions asynchronous.

First, the obvious change is to make the requestor use the new System.Web.HttpClient, with it's XXXAsync methods. In the requestor, we new up the one and only one HttpClient, because they are expensive and they handle managing connections under the covers, so it makes sense to have only the one and let it make multiple requests.

Once you switch to using the XXXAsync methods, the good news is that every PUT or POST can be sent with a FormUrlEncodedContent parameter, which can just be made of a set of key-value pairs representing the form data. This way we can let the framework take care of property form-encoding the values, as well as setting the content-type headers.

There's not a nice way to set the headers on the requests, though if the api key and user agent headers are expected to remain fairly static for each instance of the requestor they could be set once and just used everywhere else....

So! once the HttpClient.XXXAsync methods are in use, you see how things become viral. The Get/Post/Delete wrapper methods then start returning Task, and then the various Service classes start returning Task for all fo their calls.

In addition, I did a little bit of cleanup on the services themselves. I saw a common pattern where a service had an ApiKey property that was set in the constructor, so I just stuck that in a base abstract class and had them all inherit, so as to reduce code duplication. There could perhaps be more done in this area, but this is a good start :)

So once the services were done, I had to update the tests! This was a bit of a pain. MSpec doesn't do what the semantic thing is, namely allow you to declare your delegates to the various builders like so:

````
Because of = async () =>
{
var account = await _stripeAccountService.Get();
};
````

Instead, you have to do this:

````
Because of = () =>
{
StripeAccount account = _stripeAccountService.Get().Await();
};
````

Note that you cannot use var, or the Await method does not know what the type of the returned object is. You either have to have a strongly-typed object or do a direct cast on the value of the Await() call.

So that just about wraps it up, the tests all green up nicely.