30

我在 .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();
    }
}

虽然私有方法中的代码确实有效,但我遇到的问题是控制器 Get() 调用 GetResponse() 但它不等待结果,而是立即执行返回结果 = null。

我还尝试使用 WebClient 使用更简单的同步调用,如下所示:

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

        var client = new WebClient();

        result = client.DownloadString(_address);

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

效果很好。

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

4

2 回答 2

40

啊哈,我需要执行以下操作(返回任务而不是 void):

 // 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;
    }

此外,我还没有意识到我可以将 Get() 操作标记为异步,这让我可以等待外部调用。

感谢 Stephen Cleary 的博文Async and Await为我指明了正确的方向。

于 2012-11-04T21:59:17.693 回答
0

用用户名和密码调用Httpclient。在 API 需要身份验证的情况下。

    public async Task<ActionResult> Index()
{

            const string uri = "https://testdoamin.zendesk.com/api/v2/users.json?role[]=agent";
            using (var client1 = new HttpClient())
            {
                var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("test@gmail.com:123456")));///username:password for auth
                client1.DefaultRequestHeaders.Authorization = header;
               var aa = JsonConvert.DeserializeObject<dynamic>(await client1.GetStringAsync(uri));

            }
}
于 2017-12-29T12:14:36.820 回答