【问题标题】:Getting content/message from HttpResponseMessage从 HttpResponseMessage 获取内容/消息
【发布时间】:2013-04-02 21:42:06
【问题描述】:

我正在尝试获取 HttpResponseMessage 的内容。应该是:{"message":"Action '' does not exist!","success":false},但是不知道怎么从HttpResponseMessage中取出来。

HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.GetAsync("http://****?action=");
txtBlock.Text = Convert.ToString(response); //wrong!

在这种情况下 txtBlock 将具有价值:

StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  Vary: Accept-Encoding
  Keep-Alive: timeout=15, max=100
  Connection: Keep-Alive
  Date: Wed, 10 Apr 2013 20:46:37 GMT
  Server: Apache/2.2.16
  Server: (Debian)
  X-Powered-By: PHP/5.3.3-7+squeeze14
  Content-Length: 55
  Content-Type: text/html
}

【问题讨论】:

    标签: c# windows-8 windows-store-apps


    【解决方案1】:

    我认为最简单的方法就是将最后一行改为

    txtBlock.Text = await response.Content.ReadAsStringAsync(); //right!
    

    这样你就不需要引入任何流阅读器,也不需要任何扩展方法。

    【讨论】:

    • 不知道为什么这不是公认的答案,尤其是因为这使您能够轻松地将内容序列化到您的对象中。
    • ReadAsStringAsync 不能很好地处理错误恕我直言。
    • 你也可以使用 Response.Content.ReadAsStringAsync().Result 而不是 await
    • 但请注意:如果响应中有表情符号或其他一些 Unicode 字符,ReadAsStringAsync() 可能会抛出异常。我不得不使用 Streams(就像在接受的答案中一样)来克服这个问题。
    【解决方案2】:

    您需要致电GetResponse()

    Stream receiveStream = response.GetResponseStream ();
    StreamReader readStream = new StreamReader (receiveStream, Encoding.UTF8);
    txtBlock.Text = readStream.ReadToEnd();
    

    【讨论】:

    • 谢谢,但为什么我在这里得到这个错误:“System.Net.Http.HttpResponseMessage'不包含'GetResponseStream'的定义,并且没有扩展方法'GetResponseStream'接受'类型的第一个参数System.Net.Http.HttpResponseMessage' 可以找到"
    • @Klemzy - 因为您将其称为异步。尝试改用 Content 属性。看看example here。向下滚动到第二步。
    • @Klemzy - 看看example here。向下滚动到第二步。如果你不明白,我会编辑我的答案并给你一个例子
    • 这个答案完全是题外话,OP使用的是HttpClient,而不是HttpWebRequest / HttpWebResponse
    • 问题是关于 HttpCient,您的回答是基于过时和过时的 HttpWebRequest。
    【解决方案3】:

    试试这个,你可以像这样创建一个扩展方法:

        public static string ContentToString(this HttpContent httpContent)
        {
            var readAsStringAsync = httpContent.ReadAsStringAsync();
            return readAsStringAsync.Result;
        }
    

    然后,简单地调用扩展方法:

    txtBlock.Text = response.Content.ContentToString();
    

    希望对你有帮助;-)

    【讨论】:

    • 迄今为止最容易启动和运行
    • 如果您的代码无法处理异步编程,请使用 await 而不是 .Result... 或使用同步 HTTP 客户端。但是任何现代代码都应该这样做,否则它可能表明您的应用程序做错了。
    【解决方案4】:

    如果您想将其转换为特定类型(例如在测试中),您可以使用 ReadAsAsync 扩展方法:

    object yourTypeInstance = await response.Content.ReadAsAsync(typeof(YourType));
    

    或以下同步代码:

    object yourTypeInstance = response.Content.ReadAsAsync(typeof(YourType)).Result;
    

    更新:ReadAsAsync<> 还有一个通用选项,它返回特定类型的实例而不是对象声明的实例:

    YourType yourTypeInstance = await response.Content.ReadAsAsync<YourType>();
    

    【讨论】:

    • object yourTypeInstance = await response.Content.ReadAsAsync(typeof(YourType));应该是 var yourTypeInstance = await response.Content.ReadAsAsync();
    • 我使用 Request.Content.ReadAsAsync 来解析 Json 并获得了糟糕的性能。
    【解决方案5】:

    根据 rudivonstaden 的回答

    txtBlock.Text = await response.Content.ReadAsStringAsync();
    

    但如果你不想让方法异步,你可以使用

    txtBlock.Text = response.Content.ReadAsStringAsync();
    txtBlock.Text.Wait();
    

    Wait() 这很重要,因为我们正在执行异步操作,我们必须等待任务完成才能继续。

    【讨论】:

    • 使用.Result有什么不同吗?httpContent.ReadAsStringAsync().Result
    • .Result 会阻止线程在该行上的执行......而 txtBlock.Text.Wait() 阻止 wait() 调用......所以你是对的,基本上没有区别。但我怀疑txtBlock.Text.Wait() 会采用一个可选的整数参数,因此如果之前的ReadAsStringAsync() 调用永远不会返回,GUI 不会挂起。例如以下内容将阻止不超过 1 秒 txtBlock.Text.Wait(1000)
    【解决方案6】:

    我建议的快速答案是:

    response.Result.Content.ReadAsStringAsync().Result

    【讨论】:

    • 不要在任务上致电Result。您可能会锁定您的应用程序。请改用 async/await。
    • 我不会说永远不会...有时又快又脏可以完成它。但我同意您确实冒着ReadAsStringAsync() 不返回的风险,因此请确保不要在您的 GUI 或主应用程序线程上调用它。
    • 好或几乎好。我需要这样编码: HttpResponseMessage response = ....; var responseBody = 等待响应?.Content.ReadAsStringAsync();
    • 如果我正确理解您的问题,我会回答“差不多好”。根据您的代码执行模式(例如单线程或多线程)应该确定您的方法。关于您正在评论的这个答案(假设单线程执行没问题),那么我会打电话给var responseBody = response.Content.ReadAsStringAsync().Result;
    • 在任务上调用.Result 通常是不好的做法,你会阻塞主线程。
    【解决方案7】:

    我认为下图有助于那些需要以T 作为返回类型的人。

    【讨论】:

      【解决方案8】:

      你可以使用GetStringAsync方法:

      var uri = new Uri("http://yoururlhere");
      var response = await client.GetStringAsync(uri);
      

      【讨论】:

        【解决方案9】:

        使用块:

        using System;
        using System.Net;
        using System.Net.Http;
        

        此函数将创建新的 HttpClient 对象,将 http-method 设置为 GET,将请求 URL 设置为函数“Url”字符串参数,并将这些参数应用于 HttpRequestMessage 对象(定义 SendAsync 方法的设置)。最后一行:函数向指定的 url 发送异步 GET http 请求,等待响应消息的 .Result 属性(只是完整的响应对象:headers + body/content),获取该完整响应的 .Content 属性(请求的正文,没有 http headers),将 ReadAsStringAsync() 方法应用于该内容(这也是某种特殊类型的对象),最后,再次使用 .Result 属性等待此异步任务完成,以获取最终结果字符串,然后返回此字符串作为我们的函数返回。

        static string GetHttpContentAsString(string Url)
            {   
                HttpClient HttpClient = new HttpClient();
                HttpRequestMessage RequestMessage = new HttpRequestMessage(HttpMethod.Get, Url);
                return HttpClient.SendAsync(RequestMessage).Result.Content.ReadAsStringAsync().Result;
            }
        

        较短的版本,它不显示我们的 http-request 的完整“转换”路径,并使用 HttpClient 对象的 GetStringAsync 方法。函数只是创建 HttpClient 类的新实例(一个 HttpClient 对象),使用 GetStringAsync 方法将我们的 http 请求的响应主体(内容)作为异步任务结果\承诺,然后使用该异步任务结果的 .Result 属性获取最终字符串,然后简单地将这个字符串作为函数返回。

        static string GetStringSync(string Url)
            {
                HttpClient HttpClient = new HttpClient();
                return HttpClient.GetStringAsync(Url).Result;
            }
        

        用法:

        const string url1 = "https://microsoft.com";
        const string url2 = "https://stackoverflow.com";
        
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; /*sets TLC protocol version explicitly to modern version, otherwise C# could not make http requests to some httpS sites, such as https://microsoft.com*/
        
        Console.WriteLine(GetHttpContentAsString(url1)); /*gets microsoft main page html*/
        Console.ReadLine(); /*makes some pause before second request. press enter to make second request*/
        Console.WriteLine(GetStringSync(url2)); /*gets stackoverflow main page html*/
        Console.ReadLine(); /*press enter to finish*/
        

        完整代码:

        【讨论】:

          猜你喜欢
          • 2015-03-03
          • 2012-01-28
          • 1970-01-01
          • 1970-01-01
          • 2016-12-02
          • 2020-09-05
          • 2021-05-24
          • 2014-10-25
          相关资源
          最近更新 更多