从 HttpResponseMessage 获取内容/消息
Posted
技术标签:
【中文标题】从 HttpResponseMessage 获取内容/消息【英文标题】:Getting content/message from 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
【问题讨论】:
【参考方案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根据 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://***.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 *** main page html*/
Console.ReadLine(); /*press enter to finish*/
完整代码:
【讨论】:
以上是关于从 HttpResponseMessage 获取内容/消息的主要内容,如果未能解决你的问题,请参考以下文章
如何从 HttpResponseMessage 中获取特定的标头值
如何从HttpResponseMessage获取特定的标头值
异步任务<HttpResponseMessage> 获取 VS HttpResponseMessage 获取
C# 无法通过 HttpResponseMessage 获取 HTTP 返回代码