Why does the .NET Web API require a method that asynchronously reads the contents of an HTTP response, given that there is already a way to make the request asynchronously?
Because it is possible. These two methods do different things. The first sends a network request over the wire, the second reads from the received Stream .
Since both creating a network request and reading from a stream are related I / O, you can use the async api that they provide.
if I use HttpClient.GetAsync (or PostAsync, or PutAsync, etc.), is the code more asynchronous as well as asynchronously reading the content? If so, how / why?
It sounds a little strange that something is "more asynchronous." But yes, the previous example is more asynchronous than the last.
Let's try to introduce the following scenario: you create a library that is responsible for talking with a third-party service. You expose a method, call it FooAsync , which returns a very large List<Foo> . The user knows that the API is asynchronous, so it feels good to call it from the user interface thread and does not worry about blocking it for a long time.
Now let's see what happened when he makes a call with each method:
We execute FooAsync and make an http request, giving control to the caller upon reaching the first await . It then continues to hit the second await , which is read from the received stream, again returning control to the caller until it ends. At the same time, the user interface can process messages, since the basic operations are performed by async.
FooAsync and make an http request. we get control of the first await , all is well. Then we get the answer, and we read the underlying stream synchronously. While we are reading (and remember that we are reading a very large stream), the user interface stream is blocked in the I / O operation and cannot process any other messages.
Our second case is definitely undesirable and even worse, unexpected. We told the user that he gets async api, but we end up blocking quite a lot of time. Not only that, but if Task.Result is called from a user interface thread, it can be blocked.
The advantage of using await in both operations is that you create a truly asynchronous api without wasting time blocking I / O operations and do not surprise anyone who calls your method blocking.
I suggest reading Best Practices in Asynchronous Programming , which talks about all of these cases.
In conclusion, if you can switch to asynchronous "completely", do it.