Pregunta

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

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

¿Fue útil?

Solución

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 necesites reemplazar querystring con new Uri(fullUrl).Query.

Otros consejos

HttpUtility.ParseQueryString funcionará siempre que esté en una aplicación web o no le importe incluir una dependencia de 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 de Sistema.Web.Desde el Microsoft.AspNet.WebApi.Cliente paquete NuGet hay un UriExtensions.ParseQueryString, método que también se puede utilizar:

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

Así que si quieres evitar el Sistema.Web dependencia y no quieres rodar por tu cuenta, 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 tenía los requisitos previos limitados al "Subconjunto de marco solo para cliente".

Me gustó la respuesta de rp.Agregué algo de 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 fuera un poco más versátil que la que ya se proporcionaba al trabajar con consultas OLSC.

  • Los valores pueden contener varios signos iguales.
  • Decodificar caracteres codificados tanto en nombre como en valor
  • Capaz de ejecutarse en Client Framework
  • Capaz de ejecutarse 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 que no sea mala idea abordar <Extension()> en eso también para agregar la capacidad al propio Uri.

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

  1. Agregar una referencia a System.Net.Http.Formatting
  2. Agregar using System.Net.Http;
  3. Utilice 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 Cliente API web tiene un ParseQueryString método de extensión que funciona en un Uri y devuelve un HttpValueCollection:

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

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

Asegúrate de agregar una referencia (si aún no lo has hecho) a System.Net.Http en tu proyecto.

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

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();

Simplemente acceda a Request.QueryString.AllKeys mencionado como otra respuesta solo le brinda una serie de claves.

HttpUtility.ParseQueryString(Request.Url.Query) el regreso es HttpValueCollection (clase interna).Se 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 System.Web, simplemente pegue este código fuente de la clase HttpUtility.

Acabo de preparar esto a partir del código fuente de Mononucleosis infecciosa.Contiene HttpUtility y todas sus dependencias (como IHtmlString, Helpers, HttpEncoder, HttpQSCollection).

Entonces usar HttpUtility.ParseQueryString.

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

Dado que todos parecen estar pegando su solución.Aquí está el mío :-) Necesitaba esto desde una biblioteca de clases sin System.Web para recuperar parámetros de identificación de hipervínculos almacenados.

Pensé en compartirlo porque encuentro esta solución más rápida y más atractiva.

public static class Statics
    public static Dictionary<string, string> QueryParse(string url)
    {
        Dictionary<string, string> qDict = new Dictionary<string, string>();
        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")

Presione Request.QueryString.Keys para obtener una NameValueCollection de todos los parámetros de la cadena de consulta.

Para obtener todos los valores de Querystring prueba esto:

    Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring)

Dim sb As New StringBuilder("<br />")
For Each s As String In qscoll.AllKeys

  Response.Write(s & " - " & qscoll(s) & "<br />")

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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top