如何循环遍历WebHeaderCollection

33

如何在Windows Phone 7中循环遍历从HttpWebResponse获取的WebHeaderCollection以获取键和值?我们尝试使用Enumerator.Current,但这样只能获取键,而无法获取值。我们这样做是为了获取重定向URL。

12个回答

37

我认为这是一个糟糕的集合。

参见MSDN示例。我更喜欢这个:

var headers = new System.Net.WebHeaderCollection();
headers.Add("xxx", "yyy");
headers.Add("zzz", "fff");
headers.Add("xxx", "ttt");
for(int i = 0; i < headers.Count; ++i)
{
    string header = headers.GetKey(i);
    foreach(string value in headers.GetValues(i))
    {
        Console.WriteLine("{0}: {1}", header, value);
    }
}

很遗憾,没有一种方法可以在其他标题之间保持顺序获取值。

P.S. Linq风格(in LINQPad)

var items = Enumerable
                .Range(0, headers.Count)
                .SelectMany(i => headers.GetValues(i)
                    .Select(v => Tuple.Create(headers.GetKey(i), v))
                );
items.Dump();

22
“那真是一个糟糕的收藏品,我认为。” - 完全同意! - Nicholas Petersen
3
为什么不使用 Enumerable.Range(0, headers.Count).ToDictionary(i => headers.Keys[i], headers.GetValues); 代替一个元组? - drzaus
啊..将具有相同键的值分别写在单独的行上的整个想法是为了类似于HTTP标头。而SelectMany将以相同的方式乘以键。 - ony
@drzaus,GetValues返回一个数组,但这就是为什么有一个foreach的原因。Tuple用于循环遍历标题而不进行分组。WebHeaderCollection已经提供了分组访问。为什么要再创建一个看起来完全相同的东西呢?... - ony
@ony提出了一个关于“冗余”的公正观点,但是你可以更容易地传递字典(例如,不需要System.Net引用,或将Headers/Post/Get“简化”为通用格式),以及_O(1)_访问(我认为这就是OP想要的“我们这样做是为了获取重定向URL”)。我也想不到任何用例,你不希望标题保持分组。逗号和&符号在值中有什么作用--我错过了评论吗? - drzaus
显示剩余11条评论

16
foreach(string key in resp.AllKeys)
{
string value = resp[key];
}

好老的字符串数组。你也可以在它上面使用LINQ。 - Martin Capodici
1
这是指 resp.Headers.AllKeys 而不是 resp.AllKeys,然后是 resp.Headers[key] 吗? - Sepster

10

在WP7/Silverlight中,我这样做。

foreach (string key in headers.AllKeys)
{
   Console.WriteLine("头 : " + key + " ---> " + headers[key]);
}
最初的回答。

7
怎么样来谈谈C# 6 :)
string.Join("&", headers.AllKeys.Select(key => $"{key}={headers[key]}").ToList());

正是我在寻找的! - Chad Kuehn
非常完美,非常感谢!我选择使用JSON序列化:private static string JsonSerializeHeaders(System.Net.WebHeaderCollection headers) => JsonConvert.SerializeObject(headers.AllKeys.Distinct().ToDictionary(key => key, key => headers[key])); - Vedran Mandić

4

在Silverlight中。

如果你想一个接一个地获取键和值:

foreach (string key in webHeaderCollection)
{
    var value = webHeaderCollection[key];
    // do something with key and value
}

如果您需要一个键和值的字典:
var dic = webHeaderCollection.AllKeys.ToDictionary(k => webHeaderCollection[k]);
foreach (var pair in MyDic)
{
    // do something with pair.Key and pair.Value
}

2

我的解决方案,作为扩展方法:

private static string Serialize(this System.Net.WebHeaderCollection value)
{
    var response = new System.Text.StringBuilder();
    foreach (string k in value.Keys)
        response.AppendLine(k + ": " + value[k]);
    return response.ToString();
}

2

我在谷歌上搜索时发现了这个问题,当时我正在寻找一种方法从Visual Studio调试器中查看WebHeaderCollection中的键值对。

简单的解决方案(回想起来):在Watch调试窗口中使用WebHeaderCollection.ToString()方法即可完成此操作:

webheadercollection.ToString()

如果您有一个名为request的HttpWebRequest:

request.Headers.ToString()

2

我非常不喜欢在.NET中出现这样的特殊集合,因为它们不能轻松地迭代预期值。这使得事情变得不太用户友好。无论如何,如果您想要麻烦添加一个扩展方法:

// call in your main code
KeyValuePair<string, string>[] headers = webResponse.Headers.GetHeaders();

// extension: 
public static class Xtension
{
    public static KeyValuePair<string, string>[] GetHeaders(this WebHeaderCollection webHeaderCollection)
    {
        string[] keys = webHeaderCollection.AllKeys;
        var keyVals = new KeyValuePair<string, string>[keys.Length];
        for (int i = 0; i < keys.Length; i++)
            keyVals[i] = new KeyValuePair<string, string>(keys[i], webHeaderCollection[keys[i]]);
        return keyVals;
    }
}

1
为什么需要全新的键-值对集合?如果只是为了循环,那么可以返回 IEnumerable<KeyValuePair<string,string>> 而不必构建中间集合。 - ony
“你为什么需要全新的集合?”你问道? 1)AllKeys已经是一个字符串数组,如果不是,我会枚举。 2)在大多数情况下,有人需要整个集合来搜索多个标头。而我的“全新的集合”只是一个数组。 3)我绝对不是那些总是倾向于使用枚举器的人群的一部分,只是当我认为这是最好的时候。鉴于1和2,在这里我更喜欢轻量级数组,因为更常见的情况下更具性能优势,如果这将被频繁调用。但这只是我的个人喜好,你可以随意按照自己的方式做 ;) - Nicholas Petersen
有趣的是,我本以为yield return生成的IEnumerable会更高效,至少对于“不完整枚举”(即“在第一个后停止...”)来说会更高效。但正如你所说,“轻量级数组”在这两种情况下都更快 https://gist.github.com/zaus/2ce7e8a4f1e72124537f——尽管它看起来更难看;) - drzaus

0

如果你真的想使用扩展方法来获取标题列表作为KeyValuePair数组,那么你可能想要使用IEnumerable接口。

public static class WebHeaderCollectionExtensions
{
    public static IEnumerable<KeyValuePair<string, string>> GetHeaders(this System.Net.WebHeaderCollection webHeaderCollection)
    {
        string[] keys = webHeaderCollection.AllKeys;
        for (int i = 0; i < keys.Length; i++)
        {
            yield return new KeyValuePair<string, string>(keys[i], webHeaderCollection[keys[i]]);
        }
    }
}

在这种情况下,你可以很容易地使用 foreach 循环进行迭代:

foreach (var x in h.GetHeaders())
{
    Console.WriteLine(x.Key + ": " + x.Value);
}

//fix without extensions

public static IEnumerable<KeyValuePair<string, string>> GetHeaders(System.Net.WebHeaderCollection webHeaderCollection)
{
    string[] keys = webHeaderCollection.AllKeys;
    for (int i = 0; i < keys.Length; i++)
    {
        yield return new KeyValuePair<string, string>(keys[i], webHeaderCollection[keys[i]]);
    }
}

foreach (var x in GetHeaders(h))
{
    Console.WriteLine(x.Key + ": " + x.Value);
}

0

你的库的扩展方法:

public static IEnumerable<KeyValuePair<string, string>> AsEnumerable(this WebHeaderCollection headers) =>
    headers.AllKeys.Select(k => new KeyValuePair<string, string>(k, headers[k])).AsEnumerable();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接