由于问题的标题是“检索所有标题”,因此我想对此添加一个答案。
HttpResponseMessage
方法返回的有HttpClient
两个头属性:
这两个对象都实现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 的网络服务器)。
生成string
所有标题中的一个:
我们可以使用单个 Linq 表达式生成一个扁平的标题字符串:
- 用于
Concat
组合HttpResponseMessage.Headers
和HttpResponseMessage.Content.Headers
。
- 不要使用
Union
,因为这不会保留所有标题。
- (作为个人风格偏好,当我将两个
IEnumerable<T>
对象连接在一起时,我从Enumerable.Empty<T>()
视觉上对称的结果开始 - 不是出于性能或任何其他原因)。
- 在连接它们的扁平结果之前
.SelectMany
,在每个 Headers 集合上使用以扁平化每个集合。
Aggregate
与 a一起使用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
:
另一种选择是使用NameValueCollection
.NET Framework 1.1 中的经典类,它支持具有多个值的键(实际上,它在 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
);