Tengo este codigo:
NameValueCollection nv = HttpUtility.ParseQueryString(queryString);
foreach (KeyValuePair<String,String> pr in nv) {
//process KeyValuePair
}
Esto se compila, pero cuando intento ejecutarlo obtengo un archivo InvalidCastException.
¿Por qué es esto? ¿Por qué no puedo usar KeyValuePairpara iterar sobre a NameValueCollection, y qué debo usar en su lugar?

var nv = HttpUtility.ParseQueryString(Request.Url.Query); var qsDic = nv.Cast<object>().ToDictionary<object, string, object>(key => (string) key, key => nv[(string) key]);Respuestas:
En primer lugar,
NameValueCollectionno usaKeyValuePair<String,String>. Además,foreachsolo expone la clave:NameValueCollection nv = HttpUtility.ParseQueryString(queryString); foreach (string key in nv) { var value = nv[key]; }fuente
KeyValuePair<String,String>ya que NameValueCollection solo usa cadena, cadena. No es necesario especificarlo.No puede hacer eso directamente, pero puede crear un método de extensión como este:
public static IEnumerable<KeyValuePair<string, string>> AsKVP( this NameValueCollection source ) { return source.AllKeys.SelectMany( source.GetValues, (k, v) => new KeyValuePair<string, string>(k, v)); }Entonces puedes hacer:
NameValueCollection nv = HttpUtility.ParseQueryString(queryString); foreach (KeyValuePair<String,String> pr in nv.AsKVP()) { //process KeyValuePair }Nota: inspirado en esto . Se requiere SelectMany para manejar claves duplicadas.
Versión de vb.net:
<Extension> Public Function AsKVP( source As Specialized.NameValueCollection ) As IEnumerable(Of KeyValuePair(Of String, String)) Dim result = source.AllKeys.SelectMany( AddressOf source.GetValues, Function(k, v) New KeyValuePair(Of String, String)(k, v)) Return result End Functionfuente
Para referencia futura, también puede usar esta sintaxis:
foreach(string key in Request.QueryString) { var value = Request.QueryString[key]; }fuente
HttpRequestpuede omitirAllKeysya que laQueryStringpropiedad es unaNameValueCollection.AllKeyscomo mencionó @jgauffinjgauffiny las respuestas no están duplicadas si miras más de cerca.Otro método de extensión, con fines de aprendizaje:
public static IEnumerable<KeyValuePair<string, string>> ToIEnumerable(this NameValueCollection nvc) { foreach (string key in nvc.AllKeys) { yield return new KeyValuePair<string, string>(key, nvc[key]); } }fuente
nvclugar denvc.AllKeys. Me pregunto por qué los chicos de Microsoft no agregaron estoSystem.Linq. :)NameValueCollection usa el enumerador de skool antiguo:
var enu = ConfigurationManager.AppSettings.GetEnumerator(); while(enu.MoveNext()) { string key = (string)enu.Current; string value = ConfigurationManager.AppSettings[key]; }fuente
Me gustó esto y funciona:
foreach (string akey in request.Query.Keys.Cast<string>()) writer.WriteLine(akey + " = " + request.Query[akey]);fuente
Tenga en cuenta que el nombre de la clave puede aparecer más de una vez en la cadena de consulta y que la comparación suele distinguir entre mayúsculas y minúsculas.
Si solo desea obtener el valor de la primera clave coincidente y no se preocupa por el caso, use esto:
public string GetQueryValue(string queryKey) { foreach (string key in QueryItems) { if(queryKey.Equals(key, StringComparison.OrdinalIgnoreCase)) return QueryItems.GetValues(key).First(); // There might be multiple keys of the same name, but just return the first match } return null; }fuente
public static void PrintKeysAndValues2( NameValueCollection myCol ) { Console.WriteLine( " [INDEX] KEY VALUE" ); for ( int i = 0; i < myCol.Count; i++ ) Console.WriteLine( " [{0}] {1,-10} {2}", i, myCol.GetKey(i), myCol.Get(i) ); Console.WriteLine(); }http://msdn.microsoft.com/en-us/library/system.collections.specialized.namevaluecollection.aspx
fuente
NameValueCollectiondatos. Pero la pregunta es por qué no puede convertirNameValueCollectionelementos aKeyValuePair<string, string>. Quizás leíste la pregunta sin mucha atención. La mejor respuesta la diojgauffin. Una interesante solución fue propuesta porAdrian Carneiro.