使用Web API Action中的HttpClient调用外部HTTP服务

Red*_*ed1 25 c# asp.net-web-api dotnet-httpclient

我在.Net Framework 4.5上运行的ASP.Net MVC 4 Web Api项目中使用HttpClient调用外部服务

示例代码如下(忽略返回值,因为这是测试调用外部服务的示例代码):

public class ValuesController : ApiController
{
    static string _address = "http://api.worldbank.org/countries?format=json";
    private string result;

    // GET api/values
    public IEnumerable<string> Get()
    {
        GetResponse();
        return new string[] { result, "value2" };
    }

    private async void GetResponse()
    {
        var client = new HttpClient();
        HttpResponseMessage response = await client.GetAsync(_address);
        response.EnsureSuccessStatusCode();
        result = await response.Content.ReadAsStringAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然私有方法中的代码确实可以解决我的问题,但是Controller Get()调用了GetResponse(),但是它没有等待结果,而是立即执行带有result = null的返回.

我也尝试过使用WebClient进行更简单的同步调用,如下所示:

 // GET api/values
    public IEnumerable<string> Get()
    {
        //GetResponse();

        var client = new WebClient();

        result = client.DownloadString(_address);

        return new string[] { result, "value2" };
    }
Run Code Online (Sandbox Code Playgroud)

哪个工作正常.

我究竟做错了什么?为什么Get()不等待异步样本中的私有方法完成?

Red*_*ed1 36

啊哈,我需要做以下事情(返回一个任务而不是空洞):

 // GET api/values
    public async Task<IEnumerable<string>> Get()
    {
        var result = await GetExternalResponse();

        return new string[] { result, "value2" };
    }

    private async Task<string> GetExternalResponse()
    {
        var client = new HttpClient();
        HttpResponseMessage response = await client.GetAsync(_address);
        response.EnsureSuccessStatusCode();
        var result = await response.Content.ReadAsStringAsync();
        return result;
    }
Run Code Online (Sandbox Code Playgroud)

此外,我还没有意识到我可以将Get()操作标记为async,这是允许我等待外部调用的原因.

感谢Stephen Cleary的博客文章Async和Await,它指出了我正确的方向.