由于问题的标题是“检索所有标头”,我想添加一个与此相关的答案。
HttpClient
方法返回的 HttpResponseMessage
具有两个标头属性:
这两个对象都实现了 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>>>
为什么这是一个可枚举的名称集合,它包含多个值呢?因为一些HTTP头(例如Set-Cookie
)可以在响应中重复出现(尽管大多数其他标头只能出现一次 - 但软件应该优雅地处理违反RFC的Web服务器返回的无效标头)。
生成所有标头的字符串:
我们可以使用单个Linq表达式生成平面标头字符串:
- 使用
Concat
将HttpResponseMessage.Headers
和HttpResponseMessage.Content.Headers
组合在一起。
- 不要使用
Union
,因为那样不会保留所有标头。
- (作为个人风格偏好,当我将两个
IEnumerable<T>
对象连接在一起时,我从Enumerable.Empty<T>()
开始,以获得外观上对称的结果 - 不是出于性能或任何其他原因)。
- 在每个标头集合上使用
.SelectMany
来展开每个集合之前连接其平面化结果。
- 使用
Aggregate
和StringBuilder
高效生成string
表示。
就像这样:
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()
);
将所有标头加载到NameValueCollection
中:
另一种选择是使用来自.NET Framework 1.1的经典NameValueCollection
类,该类支持带有多个值的键(确实,Classic ASP.NET WebForms用于此目的):
像这样:
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
);
Error 3Cannot apply indexing with [] to an expression of type System.Net.Http.Headers.HttpResponseHeaders'
。我会更新上面的代码以便更清晰明了。 - Shulhi Sapli