C# HttpClient 检索所有标头
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16320738/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HttpClient retrieve all headers
提问by Shulhi Sapli
Currently, I am working on API wrapper. If I send a bad Consumer Key, the server will return Statusas 403 Forbiddenin the header. It will also pass custom headers. How do I actually retrieve these custom headers?
目前,我正在研究 API 包装器。如果我把一个坏的Consumer Key,服务器将返回Status如403 Forbidden在标题。它还将传递自定义标头。我如何实际检索这些自定义标头?
This is the response receive from the server.
这是从服务器收到的响应。
Cache-Control: private
Date: Wed, 01 May 2013 14:36:17 GMT
P3P: policyref="/w3c/p3p.xml", CP="ALL CURa ADMa DEVa OUR IND UNI COM NAV INT STA PRE"
Server: Apache/2.2.23 (Amazon)
Status: 403 Forbidden
X-Error: Invalid consumer key.
X-Error-Code: 152
X-Powered-By: PHP/5.3.20
Connection: keep-alive
I need to retrieve the X-Errorand X-Error-Code. Currently, I am using HttpClientclass to process the request. If I watch the headers respond under Quick Watch in VS Studio 2012, I could find it like this
我需要检索X-Error和X-Error-Code。目前,我正在使用HttpClient类来处理请求。如果我在 VS Studio 2012 中查看 Quick Watch 下的标题响应,我会发现它是这样的
((System.Net.Http.Headers.HttpHeaders)(response.Headers)).headerStore["X-Error-Code"].ParsedValue
((System.Net.Http.Headers.HttpHeaders)(response.Headers)).headerStore["X-Error-Code"].ParsedValue
Is there any other way to do this?
有没有其他方法可以做到这一点?
Edit:
headerStoreis not accessible thru code as this is private field. I only get access to it through the Quick Watch window.
编辑:
headerStore无法通过代码访问,因为这是私有字段。我只能通过 Quick Watch 窗口访问它。
This is my snippet for the request:
这是我的请求片段:
var response = await _httpClient.PostAsync("/v3/oauth/request", content);
采纳答案by Jon Skeet
Well, HttpResponseMessage.Headersreturns an HttpResponseHeadersreference, so you should be able to use GetValues()
好吧,HttpResponseMessage.Headers返回一个HttpResponseHeaders引用,所以你应该可以使用GetValues()
string error = response.Headers.GetValues("X-Error").FirstOrDefault();
string errorCode = response.Headers.GetValues("X-Error-Code").FirstOrDefault();
回答by Cameron Tinker
Just a gotcha that I found when attempting to find a header that didn't exist. You should use TryGetValues instead of GetValues because at runtime it will throw an exception if the header is not found. You would use something like this code:
只是我在尝试查找不存在的标题时发现的一个问题。您应该使用 TryGetValues 而不是 GetValues,因为在运行时如果找不到标头,它将引发异常。你会使用这样的代码:
IEnumerable<string> cookieHeader;
response.Headers.TryGetValues("Set-Cookie", out cookieHeader);
回答by Nick
Since the title of the question is "retrieve all headers", I wanted to add an answer in regards to that.
由于问题的标题是“检索所有标题”,因此我想为此添加一个答案。
The HttpResponseMessagereturned by HttpClientmethods has two header properties:
在HttpResponseMessage由归国HttpClient方法有两个头属性:
HttpResponseMessage.Headersis anHttpResponseHeaderswith generic response headersHttpResponseMessage.Content.Headersis anHttpContentHeaderswith content-specific headers likeContent-Type
HttpResponseMessage.Headers是一个HttpResponseHeaders带有通用响应头的HttpResponseMessage.Content.Headers是一个HttpContentHeaders具有特定内容的标题,如Content-Type
Both objects implement IEnumerable<KeyValuePair<string, IEnumerable<string>>, so you can easily combine all the headers with something like this:
两个对象都实现IEnumerable<KeyValuePair<string, IEnumerable<string>>,因此您可以轻松地将所有标头与以下内容组合在一起:
var responseMessage = await httpClient.GetAsync(url);
var headers = responseMessage.Headers.Concat(responseMessage.Content.Headers);
// headers has type IEnumerable<KeyValuePair<String,IEnumerable<String>>>
The reason it's an-enumerable-set-of-names-with-multiple-values is because someHTTP headers (like Set-Cookie) can be repeated in a response (even though the majority of other headers can only appear once - but software should gracefully handle an RFC-violating webserver returning invalid headers).
它是具有多个值的可枚举名称集的原因是因为某些HTTP 标头(例如Set-Cookie)可以在响应中重复(即使大多数其他标头只能出现一次 - 但软件应该优雅地处理违反 RFC 的网络服务器返回无效标头)。
Generating a stringof all headers:
生成string所有标题的一个:
We can generate a flat string of headers using a single Linq expression:
我们可以使用单个 Linq 表达式生成一个扁平的标题字符串:
- Use
Concatto combine bothHttpResponseMessage.HeadersandHttpResponseMessage.Content.Headers.- Don't use
Unionbecause that won't preserve all headers. - (As a personal style preference, when I'm concatenating two
IEnumerable<T>objects together, I start off withEnumerable.Empty<T>()for visually symmetrical results - not for performance or any other reason).
- Don't use
- Use
.SelectManyon each Headers collection to flatten each collection beforeconcatenating their flat results. - Use
Aggregatewith aStringBuilderto efficiently generate astringrepresentation.
- 使用
Concat这两个组合HttpResponseMessage.Headers和HttpResponseMessage.Content.Headers。- 不要使用,
Union因为这不会保留所有标题。 - (作为个人风格偏好,当我将两个
IEnumerable<T>对象连接在一起时,我会从Enumerable.Empty<T>()视觉上对称的结果开始——而不是出于性能或任何其他原因)。
- 不要使用,
- 在连接它们的平面结果之前,
.SelectMany在每个 Headers 集合上使用以展平每个集合。 Aggregate与 aStringBuilder一起使用可有效生成string表示。
Like so:
像这样:
HttpResponseMessage resp = await httpClient.GetAsync( url );
String allHeaders = Enumerable
.Empty<(String name, String value)>()
// Add the main Response headers as a flat list of value-tuples with potentially duplicate `name` values:
.Concat(
resp.Headers
.SelectMany( kvp => kvp.Value
.Select( v => ( name: kvp.Key, value: v ) )
)
)
// Concat with the content-specific headers as a flat list of value-tuples with potentially duplicate `name` values:
.Concat(
resp.Content.Headers
.SelectMany( kvp => kvp.Value
.Select( v => ( name: kvp.Key, value: v ) )
)
)
// Render to a string:
.Aggregate(
seed: new StringBuilder(),
func: ( sb, pair ) => sb.Append( pair.name ).Append( ": " ).Append( pair.value ).AppendLine(),
resultSelector: sb => sb.ToString()
);
Loading all headers into a NameValueCollection:
将所有标题加载到一个NameValueCollection:
Another alternative is to use the classic NameValueCollectionclass from .NET Framework 1.1, which supports keys with multiple values (indeed, it's used in Classic ASP.NET WebForms for this purpose):
另一种选择是使用NameValueCollection.NET Framework 1.1 中的经典类,它支持具有多个值的键(实际上,它在经典 ASP.NET WebForms 中用于此目的):
Like so:
像这样:
HttpResponseMessage resp = await httpClient.GetAsync( url );
NameValueCollection allHeaders = Enumerable
.Empty<(String name, String value)>()
// Add the main Response headers as a flat list of value-tuples with potentially duplicate `name` values:
.Concat(
resp.Headers
.SelectMany( kvp => kvp.Value
.Select( v => ( name: kvp.Key, value: v ) )
)
)
// Concat with the content-specific headers as a flat list of value-tuples with potentially duplicate `name` values:
.Concat(
resp.Content.Headers
.SelectMany( kvp => kvp.Value
.Select( v => ( name: kvp.Key, value: v ) )
)
)
.Aggregate(
seed: new NameValueCollection(),
func: ( nvc, pair ) => { nvc.Add( pair.name, pair.value ); return nvc; },
resultSelector: nvc => nvc
);
回答by nmishr
This works for me:
这对我有用:
(String[])response.Headers.GetValues("X-Error"))[0]
回答by da_jokker
A bit bulky, but simple to understand..
有点笨重,但很容易理解..
System.Diagnostics.Debug.Write("----- CLIENT HEADERS -----" + Environment.NewLine);
foreach (KeyValuePair<string, IEnumerable<string>> myHeader in myHttpClient.DefaultRequestHeaders)
{
System.Diagnostics.Debug.Write(myHeader.Key + Environment.NewLine);
foreach(string myValue in myHeader.Value)
{
System.Diagnostics.Debug.Write("\t" + myValue + Environment.NewLine);
}
}
System.Diagnostics.Debug.Write("----- MESSAGE HEADERS -----" + Environment.NewLine);
foreach (KeyValuePair<string, IEnumerable<string>> myHeader in myHttpRequestMessage.Headers)
{
System.Diagnostics.Debug.Write(myHeader.Key + Environment.NewLine);
foreach (string myValue in myHeader.Value)
{
System.Diagnostics.Debug.Write("\t" + myValue + Environment.NewLine);
}
}
System.Diagnostics.Debug.Write("----- CONTENT HEADERS -----" + Environment.NewLine);
foreach (KeyValuePair<string, IEnumerable<string>> myHeader in myHttpRequestMessage.Content.Headers)
{
System.Diagnostics.Debug.Write(myHeader.Key + Environment.NewLine);
foreach (string myValue in myHeader.Value)
{
System.Diagnostics.Debug.Write("\t" + myValue + Environment.NewLine);
}
}

