Cómo analizar una cadena de consulta en NameValueCollection en .NET

Me gustaría analizar una cadena como p1=6&p2=7&p3=8 en una NameValueCollection .

¿Cuál es la forma más elegante de hacer esto cuando no tiene acceso al objeto Page.Request ?

Hay una utilidad .NET incorporada para esto: HttpUtility.ParseQueryString

 // C# NameValueCollection qscoll = HttpUtility.ParseQueryString(querystring); 
 ' VB.NET Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring) 

Es posible que deba reemplazar la querystring con la new Uri(fullUrl).Query .

HttpUtility.ParseQueryString funcionará siempre que esté en una aplicación web o no le moleste incluir una dependencia en System.Web. Otra forma de hacer esto es:

 NameValueCollection queryParameters = new NameValueCollection(); string[] querySegments = queryString.Split('&'); foreach(string segment in querySegments) { string[] parts = segment.Split('='); if (parts.Length > 0) { string key = parts[0].Trim(new char[] { '?', ' ' }); string val = parts[1].Trim(); queryParameters.Add(key, val); } } 

Muchas de las respuestas proporcionan ejemplos personalizados debido a la dependencia de la respuesta aceptada en System.Web . Desde el paquete Microsoft.AspNet.WebApi.Client NuGet, hay un método UriExtensions.ParseQueryString , que también se puede usar:

 var uri = new Uri("https://stackoverflow.com/a/22167748?p1=6&p2=7&p3=8"); NameValueCollection query = uri.ParseQueryString(); 

Por lo tanto, si desea evitar la dependencia de System.Web y no desea ejecutar la suya propia, esta es una buena opción.

Quería eliminar la dependencia de System.Web para poder analizar la cadena de consulta de una implementación de ClickOnce, mientras que los requisitos previos estaban limitados al “subconjunto de infraestructura de solo cliente”.

Me gustó la respuesta de rp. Agregué alguna lógica adicional.

 public static NameValueCollection ParseQueryString(string s) { NameValueCollection nvc = new NameValueCollection(); // remove anything other than query string from url if(s.Contains("?")) { s = s.Substring(s.IndexOf('?') + 1); } foreach (string vp in Regex.Split(s, "&")) { string[] singlePair = Regex.Split(vp, "="); if (singlePair.Length == 2) { nvc.Add(singlePair[0], singlePair[1]); } else { // only one key with no value specified in query string nvc.Add(singlePair[0], string.Empty); } } return nvc; } 

Necesitaba una función que es un poco más versátil que la que ya se proporcionó cuando se trabaja con consultas OLSC.

  • Los valores pueden contener múltiples signos iguales
  • Descodificar caracteres codificados en nombre y valor
  • Capaz de ejecutar en Client Framework
  • Capaz de ejecutar en Mobile Framework.

Aquí está mi solución:

 Public Shared Function ParseQueryString(ByVal uri As Uri) As System.Collections.Specialized.NameValueCollection Dim result = New System.Collections.Specialized.NameValueCollection(4) Dim query = uri.Query If Not String.IsNullOrEmpty(query) Then Dim pairs = query.Substring(1).Split("&"c) For Each pair In pairs Dim parts = pair.Split({"="c}, 2) Dim name = System.Uri.UnescapeDataString(parts(0)) Dim value = If(parts.Length = 1, String.Empty, System.Uri.UnescapeDataString(parts(1))) result.Add(name, value) Next End If Return result End Function 

Puede no ser una mala idea conectar en eso también para agregar la capacidad a Uri.

Para hacer esto sin System.Web , sin escribirlo usted mismo, y sin paquetes NuGet adicionales:

  1. Agregue una referencia a System.Net.Http.Formatting
  2. Agregar using System.Net.Http;
  3. Usa este código:

     new Uri(uri).ParseQueryString() 

https://msdn.microsoft.com/en-us/library/system.net.http.uriextensions(v=vs.118).aspx

  private void button1_Click( object sender, EventArgs e ) { string s = @"p1=6&p2=7&p3=8"; NameValueCollection nvc = new NameValueCollection(); foreach ( string vp in Regex.Split( s, "&" ) ) { string[] singlePair = Regex.Split( vp, "=" ); if ( singlePair.Length == 2 ) { nvc.Add( singlePair[ 0 ], singlePair[ 1 ] ); } } } 

Me acabo de dar cuenta de que Web API Client tiene un método de extensión ParseQueryString que funciona en un Uri y devuelve un HttpValueCollection :

 var parameters = uri.ParseQueryString(); string foo = parameters["foo"]; 

Simplemente acceda a Request.QueryString. AllKeys mencionado como otra respuesta solo te ofrece una matriz de claves.

HttpUtility.ParseQueryString(Request.Url.Query) return es HttpValueCollection (clase interna). Hereda de NameValueCollection .

  var qs = HttpUtility.ParseQueryString(Request.Url.Query); qs.Remove("foo"); string url = "~/Default.aspx"; if (qs.Count > 0) url = url + "?" + qs.ToString(); Response.Redirect(url); 

Si no desea la dependencia de System.Web, simplemente pegue este código fuente de la clase HttpUtility.

Acabo de batir esto juntos desde el código fuente de Mono . Contiene HttpUtility y todas sus dependencias (como IHtmlString, Helpers, HttpEncoder, HttpQSCollection).

Luego use HttpUtility.ParseQueryString .

https://gist.github.com/bjorn-ali-goransson/b04a7c44808bb2de8cca3fc9a3762f9c

Dado que todo el mundo parece estar pegando su solución … aquí está el mío 🙂 Lo necesitaba desde una biblioteca de clases sin System.Web para obtener los parámetros de identificación de los hipervínculos almacenados.

Pensé que compartiría porque creo que esta solución es más rápida y de mejor apariencia.

 public static class Statics public static Dictionary QueryParse(string url) { Dictionary qDict = new Dictionary(); foreach (string qPair in url.Substring(url.IndexOf('?') + 1).Split('&')) { string[] qVal = qPair.Split('='); qDict.Add(qVal[0], Uri.UnescapeDataString(qVal[1])); } return qDict; } public static string QueryGet(string url, string param) { var qDict = QueryParse(url); return qDict[param]; } } 

Uso:

 Statics.QueryGet(url, "id") 

Si desea evitar la dependencia de System.Web que se requiere para usar HttpUtility.ParseQueryString , puede usar el método de extensión Uri ParseQueryString encuentra en System.Net.Http .

Asegúrese de agregar una referencia (si aún no lo hizo) a System.Net.Http en su proyecto.

Tenga en cuenta que debe convertir el cuerpo de la respuesta a un Uri válido para que ParseQueryString (en System.Net.Http ).

 string body = "value1=randomvalue1&value2=randomValue2"; // "http://localhost/query?" is added to the string "body" in order to create a valid Uri. string urlBody = "http://localhost/query?" + body; NameValueCollection coll = new Uri(urlBody).ParseQueryString(); 

Pulsa arriba Request.QueryString.Keys para una NameValueCollection de todos los parámetros de cadena de consulta.

Para obtener todos los valores de Querystring, intente esto:

  Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring) Dim sb As New StringBuilder("
") For Each s As String In qscoll.AllKeys Response.Write(s & " - " & qscoll(s) & "
") Next s
  var q = Request.QueryString; NameValueCollection qscoll = HttpUtility.ParseQueryString(q.ToString()); 

Traduzco a la versión C # de josh-brown en VB

 private System.Collections.Specialized.NameValueCollection ParseQueryString(Uri uri) { var result = new System.Collections.Specialized.NameValueCollection(4); var query = uri.Query; if (!String.IsNullOrEmpty(query)) { var pairs = query.Substring(1).Split("&".ToCharArray()); foreach (var pair in pairs) { var parts = pair.Split("=".ToCharArray(), 2); var name = System.Uri.UnescapeDataString(parts[0]); var value = (parts.Length == 1) ? String.Empty : System.Uri.UnescapeDataString(parts[1]); result.Add(name, value); } } return result; } 

Este es mi código, creo que es muy útil:

 public String GetQueryString(string ItemToRemoveOrInsert = null, string InsertValue = null ) { System.Collections.Specialized.NameValueCollection filtered = new System.Collections.Specialized.NameValueCollection(Request.QueryString); if (ItemToRemoveOrInsert != null) { filtered.Remove(ItemToRemoveOrInsert); if (!string.IsNullOrWhiteSpace(InsertValue)) { filtered.Add(ItemToRemoveOrInsert, InsertValue); } } string StrQr = string.Join("&", filtered.AllKeys.Select(key => key + "=" + filtered[key]).ToArray()); if (!string.IsNullOrWhiteSpace(StrQr)){ StrQr="?" + StrQr; } return StrQr; }