【问题标题】:async calls using HttpClient on MVC4在 MVC4 上使用 HttpClient 进行异步调用
【发布时间】:2013-03-07 15:11:09
【问题描述】:

我正在使用 .net 4.5 中的这项新技术,我想检查此调用的代码以及我应该如何控制错误或异步调用的响应。 调用运行良好,我需要完全控制从我的服务返回的可能错误。

这是我的代码:

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;

namespace TwitterClientMVC.Controllers
{
    public class Tweets
    {
        public Tweet[] results;
    }

    public class Tweet
    {
        [JsonProperty("from_user")]
        public string UserName { get; set; }

        [JsonProperty("text")]
        public string TweetText { get; set; }
    }
}

public async Task<ActionResult> Index()
{                                             
    Tweets model = null;

    HttpClient client = new HttpClient();

    HttpResponseMessage response = await client.GetAsync("http://mywebapiservice");

    response.EnsureSuccessStatusCode();

    model = JsonConvert.DeserializeObject<Tweets>(response.Content.ReadAsStringAsync().Result);

    return View(model.results);            
}

这是更好的方法吗?或者我错过了什么? 谢谢

我重构了,这个方法也是异步的吗?

public async Task<ActionResult> Index() 
    {
        Tweets model = null;
        using (HttpClient httpclient = new HttpClient())
        {
            model = JsonConvert.DeserializeObject<Tweets>(
                await httpclient.GetStringAsync("http://search.twitter.com/search.json?q=pluralsight")
            );
        }
        return View(model.results);
    }

【问题讨论】:

    标签: asp.net-mvc asp.net-4.5


    【解决方案1】:

    这是更好的方法吗?

    如果您的远程服务返回的状态码不是 2xx,response.EnsureSuccessStatusCode(); 将引发异常。因此,如果您想自己处理错误,您可能希望使用 IsSuccessStatusCode 属性:

    public async Task<ActionResult> Index()
    {                                             
        using (HttpClient client = new HttpClient())
        {
            var response = await client.GetAsync("http://mywebapiservice");
    
            string content = await response.Content.ReadAsStringAsync();
            if (response.IsSuccessStatusCode)
            {
                var model = JsonConvert.DeserializeObject<Tweets>(content);
                return View(model.results);            
            }
    
            // an error occurred => here you could log the content returned by the remote server
            return Content("An error occurred: " + content);
        }
    }
    

    【讨论】:

    • 对不起,我还有一个问题,如果这个方法真的是异步的,我怎么能确定在DeserializeObject的那一刻,web服务已经完成了?
    • 我已经更新了我的答案。你应该使用string content = await response.Content.ReadAsStringAsync();。这将确保在执行到达DeserializeObject 调用时,客户端已完成执行请求并读取结果。我的原始代码是同步和阻塞的,因为我在读取的内容上调用了.Result 属性。这意味着它也保证了执行已经完成,但它是同步的。最好使用await,这是真正的异步处理。
    • 谢谢,所以我们需要在 GetAsync 调用中以及在使用 ReadAsStringAsync 时使用它。 IsSuccessStatusCode 呢?在那一刻,我们确定通话结束了吗?
    • 是的,您应该在两次通话中都使用它,是的,可以保证在您点击IsSuccessStatusCode 时,通话已经完成。
    • 我在第一篇文章中用新方法做了修改,这个方法也是异步的吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    • 2020-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多