So analysieren Sie eine Abfragezeichenfolge in einer NameValueCollection in .NET

186

Ich möchte eine Zeichenfolge wie p1=6&p2=7&p3=8in a analysieren NameValueCollection.

Was ist die eleganteste Art, dies zu tun, wenn Sie keinen Zugriff auf das Page.RequestObjekt haben?

Nathan Smith
quelle

Antworten:

356

Hierfür gibt es ein integriertes .NET-Dienstprogramm: HttpUtility.ParseQueryString

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

Sie können ersetzen müssen querystringmit new Uri(fullUrl).Query.

Guy Starbuck
quelle
26
Omar, es hat bei ASP.NET 4 nicht funktioniert, es hat den Schlüssel " stackoverflow.com?para " anstelle von "para" zurückgegeben. Ich verwende also HttpUtility.ParseQueryString (neues Uri (fullUrl) .Query), das für mich korrekt funktioniert.
Michael
2
qscoll ["p1"], qscoll ["p2"] und qscoll ["p3"]
SMUsamaShah
5
ParseQueryString ist eine wirklich schlechte Idee für die Verwendung in Desktop-Anwendungen, da es nicht im Client-Profil enthalten ist. Warum sollten 100 Millionen zusätzliche Bibliotheken auf dem Client-Computer installiert werden, um nur eine einfache Methode zu verwenden? Es sieht jedoch so aus, als hätte Microsoft keine bessere Idee. Die einzige Möglichkeit besteht darin, eine eigene Methode zu implementieren oder eine Open Source-Implementierung zu verwenden.
Vitalii
2
VASoftOnline: In diesem Fall können Sie die Mono-Implementierung von ParseQueryString verwenden: github.com/mono/mono/blob/master/mcs/class/System.Web/… Die Lizenz dafür lautet MIT X11: github.com/mono/mono / blob / master / LIZENZ
sw.
3
HttpUtility.ParseQueryStringwäre meine Empfehlung, außer dass es im Fall des HttpUtility.ParseQueryString("&X=1&X=2&X=3")Ergebnisses ....X=1,2,3...ungewöhnlich ist, mehrere Parameter mit demselben Namen zu haben, aber zur Unterstützung von Controller-Parametern wie int [], IEnumerable <int> usw. erforderlich sind (solche Parameter können zur Unterstützung mehrerer Kontrollkästchen verwendet werden). Siehe "Mehrere Vorkommen derselben Abfragezeichenfolgenvariablen werden in einem Eintrag konsolidiert" gemäß MS-Site . Eine handgefertigte Version der Methode könnte Ihre einzige Option sein
Dunxz
43

HttpUtility.ParseQueryString funktioniert so lange, wie Sie sich in einer Webanwendung befinden oder es Ihnen nichts ausmacht, eine Abhängigkeit von System.Web einzuschließen. Ein anderer Weg, dies zu tun, ist:

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);
   }
}
Scott Dorman
quelle
5
Sie sollten überprüfen, ob Teile.Länge> 1, um sicherzugehen, dass Sie Teile [1]
Alexandru Pupsa
2
Was ist, wenn es keinen Wert gibt? zB kann eine Abfragezeichenfolge aussehen ?foo=1&bar. HttpUtilitywürde es analysieren als{ key = null, value = "bar" }
Thomas Levesque
Dies ist großartig im Vergleich zu HttpUtility.ParseQueryString, da es die Werte nicht decodiert (so dass Base64-codierte Werte erhalten bleiben)
CRice
1
Tatsächlich müssen Sie noch den Wert '=' zulassen, zum Beispiel & code = A0SYw34Hj / m ++ lH0s7r0l / yg6GWdymzSCbI2zOn3V4o = wird das letzte '=' Zeichen entfernt. Ich habe einen Teil Ihres Codes neu geschrieben, um den ersten Index von '=' zu erhalten und den Schlüssel und den Wert zu unterteilen, um dies zu beheben (anstatt split zu verwenden).
CRice
28

Viele der Antworten enthalten benutzerdefinierte Beispiele, da die akzeptierte Antwort von System.Web abhängt . Aus dem NuGet-Paket Microsoft.AspNet.WebApi.Client gibt es eine UriExtensions.ParseQueryString- Methode, die auch verwendet werden kann:

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

Wenn Sie also die System.Web- Abhängigkeit vermeiden und keine eigene rollen möchten, ist dies eine gute Option.

James Skimming
quelle
3
Die gleiche Funktion existiert als Erweiterung im System.Net.Http-Namespace (siehe meine Antwort unten), keine weitere vollständige Abhängigkeit
erforderlich
@jvenema Woher fügen Sie die System.Net.Http.Formatting-Abhängigkeit hinzu? Ich glaube, sie wird nur durch Hinzufügen des Microsoft.AspNet.WebApi.Client NuGet-Pakets bereitgestellt.
James Skimming
19

Ich wollte die Abhängigkeit von System.Web entfernen, damit ich die Abfragezeichenfolge einer ClickOnce-Bereitstellung analysieren kann, während die Voraussetzungen auf die "Nur-Client-Framework-Teilmenge" beschränkt sind.

Ich mochte die Antwort von rp. Ich habe eine zusätzliche Logik hinzugefügt.

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;
    }
Densom
quelle
Dies ist sehr hilfreich für Windows Phone. Sie müssen lediglich die "NameValueCollection" durch eine "SortedDictionnary <string, string>" ersetzen
Mike Bryant,
4
Seien Sie vorsichtig, wenn Sie NameValueCollection für ein Wörterbuch wechseln - sie sind nicht gleich! Abfragezeichenfolgen unterstützen mehrere Schlüssel mit demselben Wert, ebenso wie die NameValueCollection.
Matt DeKrey
7

Ich brauchte eine Funktion, die etwas vielseitiger ist als die, die bereits bei der Arbeit mit OLSC-Abfragen bereitgestellt wurde.

  • Werte können mehrere Gleichheitszeichen enthalten
  • Dekodieren Sie codierte Zeichen in Name und Wert
  • Kann auf Client Framework ausgeführt werden
  • Kann auf Mobile Framework ausgeführt werden.

Hier ist meine Lösung:

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

Es ist vielleicht keine schlechte Idee, auch das in Angriff <Extension()>zu nehmen, um Uri selbst die Fähigkeit zu verleihen.

Josh Brown
quelle
7

Um dies ohne System.Web, ohne selbst zu schreiben und ohne zusätzliche NuGet-Pakete zu tun :

  1. Fügen Sie einen Verweis auf hinzu System.Net.Http.Formatting
  2. Hinzufügen using System.Net.Http;
  3. Verwenden Sie diesen Code:

    new Uri(uri).ParseQueryString()

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

jvenema
quelle
3
Woher fügen Sie die System.Net.Http.Formatting-Abhängigkeit hinzu? Ich glaube, sie wird nur durch Hinzufügen des Microsoft.AspNet.WebApi.Client NuGet-Pakets bereitgestellt.
James Skimming
Huh, mein schlechtes. Ich denke, es wurde mit dem MVC-Framework geliefert, das automatisch installiert wurde, sodass ich keine zusätzlichen Pakete hinzufügen musste (Programme (x86) \ Microsoft ASP.NET \ ASP.NET MVC 4 \ Assemblies \ System.Net). Http.Formatting.dll)
Jvenema
System.Net.Formatting EXTENSION VS2019 ist eine separate Liste oder Registerkarte von den traditionellen Framework-Referenzen
SQL Surfer
3

Wenn Sie die Abhängigkeit von System.Web vermeiden möchten, die für die Verwendung von HttpUtility.ParseQueryString erforderlich ist , können Sie die UriErweiterungsmethode ParseQueryStringin verwenden System.Net.Http.

Stellen Sie sicher, dass Sie System.Net.HttpIhrem Projekt eine Referenz hinzufügen (falls Sie dies noch nicht getan haben) .

Beachten Sie, dass Sie den Antworttext in einen gültigen konvertieren müssen, Uridamit ParseQueryString(in System.Net.Http) funktioniert.

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();
Amadeus Sánchez
quelle
Mit System.Net.Formatting EXTENSION VS2019 werden Erweiterungsreferenzen von herkömmlichen Framework-Referenzen getrennt.
SQL Surfer
2
    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 ] );    
            }    
        }
    }
rp.
quelle
5
Semikolon ist auch als Parametertrennzeichen in http erlaubt, besser, um das Rad nicht neu zu erfinden
Matthew Lock
2

Ich habe gerade festgestellt, dass der Web-API-Client eine ParseQueryStringErweiterungsmethode hat, die auf a funktioniert Uriund Folgendes zurückgibt HttpValueCollection:

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

Greifen Sie einfach auf Request.QueryString zu. AllKeys, das als weitere Antwort erwähnt wird, bietet Ihnen nur eine Reihe von Schlüsseln.

Bluthund
quelle
1

HttpUtility.ParseQueryString(Request.Url.Query)return is HttpValueCollection(interne Klasse). Es erbt von 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); 
alex1kirch
quelle
1

Da jeder seine Lösung einzufügen scheint .. hier ist meine :-) Ich brauchte diese aus einer Klassenbibliothek heraus, ohne System.WebID-Parameter von gespeicherten Hyperlinks abzurufen.

Ich dachte, ich würde teilen, weil ich diese Lösung schneller finde und besser aussehe.

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];
    }
}

Verwendung:

Statics.QueryGet(url, "id")
Tiele Declercq
quelle
1
Nur ein Problem bei dieser Methode: Eine Abfragezeichenfolge kann für einen bestimmten Parameter mehr als einen Wert haben. In diesem Fall gibt Ihre Methode einen doppelten Schlüsselfehler aus.
Thomas Levesque
Ja, verwenden Sie zumindest eine NameValueCollection. Abfrageringe mit doppelten Schlüsseln sind vollkommen legal.
Chad Grant
Außerdem unterscheidet Ihr Wörterbuch zwischen Groß- und Kleinschreibung, sodass X = 1 und x = 1 unterschiedliche Schlüssel sind. Benötigen Sie ein neues Wörterbuch <string, string> (StringComparer.OrdinalIgnoreCase);
Chad Grant
0

Klicken Sie auf Request.QueryString.Keys, um eine NameValueCollection aller Abfragezeichenfolgenparameter zu erhalten.

Mark Glorie
quelle
0

Um alle Querystring-Werte zu erhalten, versuchen Sie Folgendes:

    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
mirko cro 1234
quelle
0
        var q = Request.QueryString;
        NameValueCollection qscoll = HttpUtility.ParseQueryString(q.ToString());
Hamit YILDIRIM
quelle
0
let search = window.location.search;

console.log(search);

let qString = search.substring(1);

while(qString.indexOf("+") !== -1)

   qString  = qString.replace("+", "");

let qArray = qString.split("&");

let values = [];

for(let i = 0; i < qArray.length; i++){
   let pos = qArray[i].search("=");
   let keyVal = qArray[i].substring(0, pos);
   let dataVal = qArray[i].substring(pos + 1);
   dataVal = decodeURIComponent(dataVal);
   values[keyVal] = dataVal;
}
Nahom Haile
quelle
-1

Ich übersetze in VB in die C # -Version von Josh-Brown

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;
}
Elgoya
quelle
-2

Dies ist mein Code, ich denke, es ist sehr nützlich:

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;
}
Farhawd
quelle