How do you loop through a WebHeaderCollection
got from HttpWebResponse
in Windows phone 7 to get keys and values? We've tried Enumerator.Current
; with this, we are only getting the keys, not the values. We are doing this to get a redirected URL.

- 12,864
- 16
- 78
- 107

- 1,243
- 2
- 13
- 31
12 Answers
That's an awful collection, I think.
See MSDN sample. I'd prefer this one:
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);
}
}
Unfortunately there is no way to get values with order preserving between other headers.
P.S. Linq style (in LINQPad)
var items = Enumerable
.Range(0, headers.Count)
.SelectMany(i => headers.GetValues(i)
.Select(v => Tuple.Create(headers.GetKey(i), v))
);
items.Dump();

- 12,457
- 1
- 33
- 41
-
22'That's an awful collection, I think.' - couldn't agree more! – Nicholas Petersen Jan 26 '14 at 22:39
-
3instead of a Tuple, why not `Enumerable.Range(0, headers.Count).ToDictionary(i => headers.Keys[i], headers.GetValues);` – drzaus Apr 11 '14 at 10:09
-
Arghh.. Whole idea of writing values with same key on a separate line is to resemble HTTP headers. And `SelectMany` will multiply keys in a same way. – ony Jan 07 '16 at 18:23
-
@drzaus, `GetValues` returns an array, but that's why there is a `foreach` for. `Tuple` is to loop though headers without grouping. `WebHeaderCollection` already provides grouped access. Why would you make yet another which is looks exactly the same?... – ony Jan 07 '16 at 18:27
-
@drzaus, @JonSchneider, `","` and `"&"` - can be part HTTP header value. – ony Jan 07 '16 at 18:31
-
@ony a fair point about "redundancy", but you can pass around a dictionary "more easily" (e.g. without requiring `System.Net` references, or "simplifying" Headers/Post/Get to a common format) as well as _O(1)_ access (which I think is what the OP was going for with "We are doing this to get a redirected URL"). I also couldn't think of a use case where you _wouldn't_ want the headers to remain grouped. What do `,` and `&` in values have to do with anything -- am I missing a comment? – drzaus Jan 13 '16 at 16:33
-
@drzaus, since my answer it was edited to write all values for same HTTP header separated either with `,` or with `&`. When you see them in output you cannot say what content of each header is because characters might be part of headers itself. – ony Jan 16 '16 at 15:38
-
@drzaus, I guess walking through collection and returning found header is better than building a dictionary and lookup in it unless you plan to do multiple lookups. I'm not sure I understand what you mean under "more easily" in this case and what you refer with `System.Net` reference. – ony Jan 16 '16 at 15:44
-
Old stuff here - but fyi this answer didn't work properly for me. headers.GetValues(i) returns only at most one value. For example, try it with set-cookie, where headers.GetValues("set-cookie") will work. – jws Jul 30 '20 at 21:02
-
@jws, that sounds like a bug since as per [docs](https://learn.microsoft.com/en-us/dotnet/api/system.net.webheadercollection.getvalues?view=netcore-3.1) both `GetValues` overloads gives collection and have identical documentation on return "An array of header strings". It sounds weird to return `string[]` with at most one element :) . I don't have where to test it, but I'd suggest to ensure that you test both on same collection (e.g. construct `WebHeaderCollection` in test rather than processing actual response). – ony Aug 01 '20 at 09:39
-
@jws, [it looks like it still works at least on ideone](https://ideone.com/AFX2U4). I'm curious about your example with `set-cookie`. Can you share it? – ony Aug 01 '20 at 10:01
-
OK code above does work, but differently than I expected. GetValues(i) returns all the cookies together on one line, while GetValues(header) returns multiple items and so there are multiple value lines. GetValues(i): prints one line `Set-Cookie: FOO=blah; Path=/; blah;, BAR=blah; Path=/; blah` GetValues(header): prints multiple lines `Set-Cookie: FOO=blah; Path:/; blah;` \n `Set-Cookie: BAR=blah; Path:/; blah;` ... I used `blah` to shorten the details. – jws Aug 01 '20 at 17:45
-
@jws, something is weird. Can you share minimal version of your code? Both methods `GetValues` should return only header value like `FOO=blah; Path=/; blah;, BAR=blah; Path=/; blah`. [Here example with calling both and results are identical](https://ideone.com/Vomo9s). Maybe you are using some broken implementation? – ony Aug 01 '20 at 18:48
-
The behavior looks like it is in the response side, and not the request side. BTW ideone will not be able to run the code as it blocks web traffic. https://ideone.com/NZoHqz – jws Aug 01 '20 at 21:50
-
@jws, any chance that your server returns non-compliant response and puts`Set-Cookie: ...\nSet-Cookie: ...` instead of separating them with `\r\n` (CR LF) as per [RFC 2616 (HTTP)](https://tools.ietf.org/html/rfc2616#page-15) and thus parser treats it as a single header actually? – ony Aug 03 '20 at 07:32
-
It reproduces with www.yahoo.com. – jws Aug 04 '20 at 14:23
foreach(string key in resp.AllKeys)
{
string value = resp[key];
}

- 898
- 7
- 17
-
-
1Is that meant to be `resp.Headers.AllKeys`, not `resp.AllKeys`, and then `resp.Headers[key]`? – Sepster Sep 23 '14 at 11:25
in WP7/Silverlight I do this.
foreach (string key in headers.AllKeys)
{
Console.WriteLine("Header : " + key + " ---> " + headers[key]);
}

- 4,384
- 1
- 25
- 21

- 11,367
- 11
- 50
- 60
How about some C# 6 :)
string.Join("&", headers.AllKeys.Select(key => $"{key}={headers[key]}").ToList());

- 346
- 3
- 6
-
-
Just perfect, thank you very much! I went for JSON serialization with: `private static string JsonSerializeHeaders(System.Net.WebHeaderCollection headers) => JsonConvert.SerializeObject(headers.AllKeys.Distinct().ToDictionary(key => key, key => headers[key]));` – Vedran Mandić Mar 28 '22 at 08:50
In Silverlight.
If you want the keys and values one by one:
foreach (string key in webHeaderCollection)
{
var value = webHeaderCollection[key];
// do something with key and value
}
If you want a dictionary of keys and values:
var dic = webHeaderCollection.AllKeys.ToDictionary(k => webHeaderCollection[k]);
foreach (var pair in MyDic)
{
// do something with pair.Key and pair.Value
}

- 37,241
- 25
- 195
- 267
I really don't like it when special collections like this exist at times in .NET that are not easily iterated over for expected values. Makes things a lot less user friendly. Anyway, if you felt like going to the trouble of adding an extension method:
// 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;
}
}

- 9,104
- 7
- 59
- 69
-
1Why would you need totally new collection of key-value pairs? If its only for looping through then you can return `IEnumerable
>` without building intermediate collection. – ony Jan 26 '14 at 07:22 -
'Why would you need totally new collection' you ask? 1) AllKeys is already a string[], if it weren't, I would enumerate. 2) In most use cases someone would need the whole collection, to search for multiple headers. And my 'totally new collection' is just an array. 3) I definitely am not part of the crowd that always gravitates to enumerators whenever they can, just when I think it is *best*. Given 1 and 2, I prefer a lightweight array here as more often a bit more performant, if this is going to be called a lot. But that's my preference, feel free to do it your way ;) – Nicholas Petersen Jan 26 '14 at 21:50
-
interesting, I would have thought an `IEnumerable` from `yield return` be more performant, at least for "incomplete enumeration" (i.e. "stop after first...") but as you say the 'lightweight array' is faster in both cases https://gist.github.com/zaus/2ce7e8a4f1e72124537f -- still uglier though ;) – drzaus Jan 13 '16 at 17:04
I landed on this question from Google while I was trying to find a way to view the key-value pairs in a WebHeaderCollection from the Visual Studio debugger.
Simple solution (in retrospect): The WebHeaderCollection.ToString() method, used in the Watch debugging window, will accomplish this:
webheadercollection.ToString()
So, if you have an HttpWebRequest named request
:
request.Headers.ToString()

- 25,758
- 23
- 142
- 170
My solution, as an extension method:
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,041
- 1
- 18
- 23
If you really want to use extension method to achieve getting list of headers as KeyValuePair array you may want to use IEnumerable interface.
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]]);
}
}
}
In this case you can iterate in foreach loop easy way:
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);
}

- 5,656
- 10
- 72
- 124

- 89
- 1
- 2
Extension method for your library:
public static IEnumerable<KeyValuePair<string, string>> AsEnumerable(this WebHeaderCollection headers) =>
headers.AllKeys.Select(k => new KeyValuePair<string, string>(k, headers[k])).AsEnumerable();

- 71
- 4
For i As Integer = 0 To Response.Headers.Count - 1
'Response.Headers.Get(i)
Next

- 24,900
- 17
- 97
- 124
foreach(string item in response.Headers) {
string key = item.ToString();
if (key == "x-ng-sessionid") {
sessionid = response.Headers[item];
}
}

- 535
- 1
- 5
- 10