it-swarm-pt.tech

Como analisar uma cadeia de consulta em um NameValueCollection no .NET

Eu gostaria de analisar uma string como p1=6&p2=7&p3=8 em um NameValueCollection.

Qual é a maneira mais elegante de fazer isso quando você não tem acesso ao objeto Page.Request?

181
Nathan Smith

Há um utilitário .NET embutido para isso: HttpUtility.ParseQueryString

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

Você pode precisar substituir querystring por new Uri(fullUrl).Query.

345
Guy Starbuck

HttpUtility.ParseQueryString funcionará contanto que você esteja em um aplicativo da Web ou não se importe em incluir uma dependência no System.Web. Outra maneira de fazer isso é:

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);
   }
}
43
Scott Dorman

Muitas das respostas estão fornecendo exemplos personalizados por causa da dependência da resposta aceita em System.Web . Do pacote Microsoft.AspNet.WebApi.Client NuGet existe um método riExtensions.ParseQueryString , que também pode ser usado:

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

Portanto, se você quiser evitar a dependência System.Web e não quiser criar sua própria, esta é uma boa opção.

25
James Skimming

Eu queria remover a dependência de System.Web para que eu pudesse analisar a seqüência de consulta de uma implantação ClickOnce, enquanto tendo os pré-requisitos limitados ao "Subconjunto de estrutura somente de cliente".

Eu gostei da resposta do rp. Eu adicionei alguma 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;
    }
19
densom

Eu precisava de uma função que fosse um pouco mais versátil do que a que já fornecia ao trabalhar com consultas OLSC.

  • Os valores podem conter vários sinais de igual
  • Decodificar caracteres codificados em nome e valor
  • Capaz de executar no Client Framework
  • Capaz de executar no Mobile Framework.

Aqui está a minha solução:

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

Pode não ser uma má idéia adicionar <Extension()> também para adicionar a capacidade ao próprio Uri.

7
Josh Brown

Para fazer isso sem System.Web, sem escrever você mesmo e sem pacotes adicionais do NuGet:

  1. Adicionar uma referência a System.Net.Http.Formatting
  2. Adicionar using System.Net.Http;
  3. Use este código:

    new Uri(uri).ParseQueryString()
    

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

7
jvenema

Acabei de perceber que Cliente da API da Web tem um método de extensão ParseQueryString que funciona em um Uri e retorna um HttpValueCollection:

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

Se você quiser evitar a dependência do System.Web que é necessário para usar HttpUtility.ParseQueryString , você pode usar o método de extensão UriParseQueryString encontrado em System.Net.Http.

Certifique-se de adicionar uma referência (se você ainda não o fez) ao System.Net.Http no seu projeto.

Observe que você precisa converter o corpo da resposta em um Uri válido para que ParseQueryString (em System.Net.Http) funcione.

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();
2
Amadeus Sánchez
    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 ] );    
            }    
        }
    }
2
rp.

Apenas acesse Request.QueryString. AllKeys mencionado como outra resposta apenas você recebe uma matriz de chaves.

1
Bloodhound

Se você não quiser a dependência System.Web, basta colar esse código-fonte da classe HttpUtility.

Eu apenas peguei isso junto do código-fonte de Mono . Ele contém o HttpUtility e todas as suas dependências (como IHtmlString, Helpers, HttpEncoder, HttpQSCollection).

Então use HttpUtility.ParseQueryString.

https://Gist.github.com/bjorn-ALi-goransson/b04a7c44808bb2de8cca3fc9a3762f9c

1
user3638471

HttpUtility.ParseQueryString(Request.Url.Query) return é HttpValueCollection (classe interna). Ele herda 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); 
1
alex1kirch

Como todo mundo parece estar colando sua solução ... aqui está o meu :-) Eu precisava disso de dentro de uma biblioteca de classes sem System.Web para buscar parâmetros de id de hyperlinks armazenados.

Pensei em compartilhar porque acho essa solução mais rápida e com melhor aparência.

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")
1
Tiele Declercq

Clique em Request.QueryString.Keys para obter um NameValueCollection de todos os parâmetros de string de consulta.

0
Mark Glorie
        var q = Request.QueryString;
        NameValueCollection qscoll = HttpUtility.ParseQueryString(q.ToString());
0
marven

Para obter todos os valores de Querystring, tente isto:

    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
0
mirko cro 1234