Wie erstelle ich eine Abfragezeichenfolge für eine URL in C #?

473

Eine häufige Aufgabe beim Aufrufen von Webressourcen aus einem Code besteht darin, eine Abfragezeichenfolge zu erstellen, die alle erforderlichen Parameter enthält. Während es auf keinen Fall eine Raketenwissenschaft gibt, gibt es einige raffinierte Details, um die Sie sich kümmern müssen, wie das Anhängen eines, &wenn nicht des ersten Parameters, das Codieren der Parameter usw.

Der Code dafür ist sehr einfach, aber etwas langweilig:

StringBuilder SB = new StringBuilder();
if (NeedsToAddParameter A) 
{ 
  SB.Append("A="); SB.Append(HttpUtility.UrlEncode("TheValueOfA")); 
}

if (NeedsToAddParameter B) 
{
  if (SB.Length>0) SB.Append("&"); 
  SB.Append("B="); SB.Append(HttpUtility.UrlEncode("TheValueOfB")); }
}

Dies ist eine so häufige Aufgabe, dass man erwarten würde, dass eine Utility-Klasse existiert, die sie eleganter und lesbarer macht. Beim Scannen von MSDN konnte ich keine finden - was mich zu der folgenden Frage bringt:

Was ist die eleganteste und sauberste Art, wie Sie das oben genannte tun?

Boas
quelle
26
Es ist ein bisschen traurig, dass es selbst zum gegenwärtigen Zeitpunkt keinen einfachen Weg zu geben scheint, mit Querystringen umzugehen. Und mit unkompliziert meine ich eine OOB, nicht interne, standardkonforme Framework-Klasse. Oder verpasse ich vielleicht etwas?
Grimasse der Verzweiflung
5
Du vermisst nichts. Querystring Building ist eine große Lücke in dem Framework, das ich mit Flurl zu füllen versucht habe .
Todd Menier
Du hast mich gerade zum Nachdenken gebracht, ich sollte einen bauen. Neuer UrlBuilder (vorhanden) .AddQuery ("Schlüssel", "Wert"). ToString ()
Demetris Leptos

Antworten:

293

Wenn Sie unter die Haube schauen, ist die QueryString-Eigenschaft eine NameValueCollection. Wenn ich ähnliche Dinge getan habe, war ich normalerweise an Serialisierung UND Deserialisierung interessiert. Mein Vorschlag ist daher, eine NameValueCollection aufzubauen und dann an folgende Adresse zu übergeben:

using System.Linq;
using System.Web;
using System.Collections.Specialized;

private string ToQueryString(NameValueCollection nvc)
{
    var array = (
        from key in nvc.AllKeys
        from value in nvc.GetValues(key)
            select string.Format(
                "{0}={1}",
                HttpUtility.UrlEncode(key),
                HttpUtility.UrlEncode(value))
        ).ToArray();
    return "?" + string.Join("&", array);
}

Ich kann mir vorstellen, dass es auch in LINQ eine super elegante Möglichkeit gibt, dies zu tun ...

Annakata
quelle
22
Die HTTP-Spezifikation (RFC 2616) sagt nichts darüber aus, was Abfragezeichenfolgen enthalten können. Auch RFC 3986, das das generische URI-Format definiert, nicht. Das häufig verwendete Schlüssel / Wert-Paar-Format wird aufgerufen application/x-www-form-urlencodedund tatsächlich durch HTML definiert, um Formulardaten als Teil einer GETAnforderung zu senden. HTML 5 verbietet nicht mehrere Werte pro Schlüssel in diesem Format. Tatsächlich muss der Browser mehrere Werte pro Schlüssel erstellen, falls die Seite (fälschlicherweise) mehrere Felder mit demselben nameAttribut enthält. Siehe goo.gl/uk1Ag
Daniel Cassidy
14
@annakata: Ich weiß, dass mein Kommentar über ein Jahr alt ist (und die Antwort über zwei Jahre alt!), aber NameValueCollection unterstützt mithilfe der GetValues ​​(Schlüssel) -Methode sehr viele Werte pro Schlüssel.
Mauricio Scheffer
4
@MauricioScheffer: Aber NameValueCollection verwandelt sich nicht "richtig" in einen Querystring. Wenn Sie beispielsweise den QueryString-Parameter in WebClient festlegen, bei dem derselbe Schlüssel mehrmals vorhanden ist, wird er zu "Pfad? Schlüssel = Wert1, Wert2" anstelle von "Pfad? Schlüssel = Wert1 & Schlüssel = Wert2", was ein allgemeiner Standard ist ?) Muster.
David Pope
8
In Bezug auf mehrere Werte pro Schlüssel glaube ich, dass in HTML, wenn Sie ein Mehrfachauswahl-Listenfeld mit mehreren ausgewählten und übermittelten Elementen haben, diese in dem von David genannten Mehrfachwertformat gesendet werden.
Sam
10
Möglicherweise möchten Sie Uri.EscapeDataString anstelle von HttpUtility.UrlEncode verwenden, das portabler ist. Siehe stackoverflow.com/questions/2573290/…
PEK
687

Sie können eine neue beschreibbare Instanz von erstellen, HttpValueCollectionindem Sie sie aufrufen System.Web.HttpUtility.ParseQueryString(string.Empty)und dann wie eine beliebige verwenden NameValueCollection. Nachdem Sie die gewünschten Werte hinzugefügt haben, können Sie ToStringdie Sammlung wie folgt aufrufen , um eine Abfragezeichenfolge abzurufen:

NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(string.Empty);

queryString.Add("key1", "value1");
queryString.Add("key2", "value2");

return queryString.ToString(); // Returns "key1=value1&key2=value2", all URL-encoded

Das HttpValueCollectionist intern und daher können Sie keine Instanz direkt erstellen. Sobald Sie jedoch eine Instanz erhalten haben, können Sie sie wie jede andere verwenden NameValueCollection. Da das eigentliche Objekt, mit dem Sie arbeiten, ein ist HttpValueCollection, ruft das Aufrufen der ToString-Methode die überschriebene Methode auf HttpValueCollection, mit der die Auflistung als URL-codierte Abfragezeichenfolge formatiert wird .

Nachdem ich SO und das Web nach einer Antwort auf ein ähnliches Problem durchsucht habe, ist dies die einfachste Lösung, die ich finden konnte.

.NET Core

Wenn Sie in .NET Core arbeiten, können Sie die Microsoft.AspNetCore.WebUtilities.QueryHelpersKlasse verwenden, was dies erheblich vereinfacht.

https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.webutilities.queryhelpers

Beispielcode:

const string url = "https://customer-information.azure-api.net/customers/search/taxnbr";
var param = new Dictionary<string, string>() { { "CIKey", "123456789" } };

var newUrl = new Uri(QueryHelpers.AddQueryString(url, param));
John Bledsoe
quelle
6
Sie könnten wahrscheinlich eine Erweiterungsmethode namens ToURLQueryString für die IDictionary-Schnittstelle erstellen:public static string ToURLQueryString(this IDictionary dict) { ... }
Roy Tinker
65
Diese Methode ist für Multibyte-Zeichen nicht standardkonform . Sie werden als% uXXXX anstelle von% XX% XX codiert. Die resultierenden Abfragezeichenfolgen werden von Webservern möglicherweise falsch interpretiert. Dies ist sogar in der internen Framework-Klasse HttpValueCollection dokumentiert, die von HttpUtility.ParseQueryString () zurückgegeben wird. Kommentar besagt, dass sie dieses Verhalten aus Gründen der Abwärtskompatibilität beibehalten.
alex
25
Beachten Sie, dass es einen wichtigen Unterschied zwischen HttpUtilityPraseQueryString ("") und neuer NameValueCollection () gibt - nur das HttpUtility-Ergebnis überschreibt ToString (), um einen ordnungsgemäßen Querystring zu erzeugen
Frank Schwieterman
7
Was ist mit Fällen, in denen Sie mehrere Instanzen eines Namens in der Abfragezeichenfolge möchten? Zum Beispiel "Typ = 10 & Typ = 21".
Finster
7
@Finster Mit der AddMethode können Sie der Abfragezeichenfolge mehrere Instanzen eines Namens hinzufügen . Das heißt, die queryString.Add("type", "1"); queryString.Add("type", "2"); Verwendung der AddMethode ist wahrscheinlich eine bessere Möglichkeit, dies die ganze Zeit tatsächlich zu tun.
jeremysawesome
94

Mit der Inspiration von Roy Tinkers Kommentar habe ich eine einfache Erweiterungsmethode für die Uri-Klasse verwendet, die meinen Code präzise und sauber hält:

using System.Web;

public static class HttpExtensions
{
    public static Uri AddQuery(this Uri uri, string name, string value)
    {
        var httpValueCollection = HttpUtility.ParseQueryString(uri.Query);

        httpValueCollection.Remove(name);
        httpValueCollection.Add(name, value);

        var ub = new UriBuilder(uri);
        ub.Query = httpValueCollection.ToString();

        return ub.Uri;
    }
}

Verwendungszweck:

Uri url = new Uri("http://localhost/rest/something/browse").
          AddQuery("page", "0").
          AddQuery("pageSize", "200");

Bearbeiten - Standardkonforme Variante

Wie mehrere Personen betonten, werden httpValueCollection.ToString()Unicode-Zeichen nicht standardkonform codiert . Dies ist eine Variante derselben Erweiterungsmethode, die solche Zeichen durch Aufrufen der HttpUtility.UrlEncodeMethode anstelle der veralteten HttpUtility.UrlEncodeUnicodeMethode behandelt.

using System.Web;

public static Uri AddQuery(this Uri uri, string name, string value)
{
    var httpValueCollection = HttpUtility.ParseQueryString(uri.Query);

    httpValueCollection.Remove(name);
    httpValueCollection.Add(name, value);

    var ub = new UriBuilder(uri);

    // this code block is taken from httpValueCollection.ToString() method
    // and modified so it encodes strings with HttpUtility.UrlEncode
    if (httpValueCollection.Count == 0)
        ub.Query = String.Empty;
    else
    {
        var sb = new StringBuilder();

        for (int i = 0; i < httpValueCollection.Count; i++)
        {
            string text = httpValueCollection.GetKey(i);
            {
                text = HttpUtility.UrlEncode(text);

                string val = (text != null) ? (text + "=") : string.Empty;
                string[] vals = httpValueCollection.GetValues(i);

                if (sb.Length > 0)
                    sb.Append('&');

                if (vals == null || vals.Length == 0)
                    sb.Append(val);
                else
                {
                    if (vals.Length == 1)
                    {
                        sb.Append(val);
                        sb.Append(HttpUtility.UrlEncode(vals[0]));
                    }
                    else
                    {
                        for (int j = 0; j < vals.Length; j++)
                        {
                            if (j > 0)
                                sb.Append('&');

                            sb.Append(val);
                            sb.Append(HttpUtility.UrlEncode(vals[j]));
                        }
                    }
                }
            }
        }

        ub.Query = sb.ToString();
    }

    return ub.Uri;
}
Vedran
quelle
3
Perfekt. Zu meiner hauseigenen Bibliothek hinzugefügt. :)
Andy
1
Sie sollten den Wert auch per URL codieren. queryString.Add (Name, Uri.EscapeDataString (Wert));
Ufuk Hacıoğulları
2
Vielen Dank für die Verbesserung dieser Antwort. Das Problem mit Multibyte-Zeichen wurde behoben.
Ufuk Hacıoğulları
9
Nebenbei bemerkt, dies funktioniert nicht mit relativen URLs, da Sie den UriBuilder nicht von einem relativen Uri instanziieren können.
Yuriy Faktorovich
1
Ich habe einen Entfernungsschlüssel hinzugefügt, damit kein Duplikat hinzugefügt werden kann. dotnetfiddle.net/hTlyAd
Paul Totzke
29

Ich habe vor einiger Zeit eine ähnliche Frage beantwortet . Grundsätzlich ist es am besten, die Klasse zu verwenden HttpValueCollection, die Request.QueryStringeigentlich die Eigenschaft von ASP.NET ist. Leider ist sie im .NET Framework intern. Sie können Reflector verwenden, um es zu greifen (und es in Ihre Utils-Klasse zu legen). Auf diese Weise können Sie die Abfragezeichenfolge wie eine NameValueCollection bearbeiten, wobei jedoch alle Probleme mit der URL-Codierung / -Decodierung behoben sind.

HttpValueCollectionwird erweitert NameValueCollectionund verfügt über einen Konstruktor, der eine codierte Abfragezeichenfolge (einschließlich kaufmännisches Und und Fragezeichen) verwendet und eine ToString()Methode überschreibt , mit der die Abfragezeichenfolge später aus der zugrunde liegenden Auflistung neu erstellt werden kann.

Beispiel:

  var coll = new HttpValueCollection();

  coll["userId"] = "50";
  coll["paramA"] = "A";
  coll["paramB"] = "B";      

  string query = coll.ToString(true); // true means use urlencode

  Console.WriteLine(query); // prints: userId=50&paramA=A&paramB=B
Igal Tabachnik
quelle
Vielen Dank ... Ich habe festgestellt, dass die zurückgegebene NameValueCollection einen ToString () hat, der sich anders verhält, aber nicht herausfinden kann, warum.
Calebt
httpValueCollection.ToString()ruft tatsächlich an, httpValueCollection.ToString(true)so dass das Hinzufügen der trueExplizität nicht erforderlich ist.
Dav_i
5
HttpValueCollection ist eine interne Klasse, daher können Sie sie nicht instanziieren.
Ozba
29

Hier ist eine fließende / lambda-artige Methode als Erweiterungsmethode (Kombination von Konzepten in früheren Beiträgen), die mehrere Werte für denselben Schlüssel unterstützt. Meine persönliche Präferenz sind Erweiterungen gegenüber Wrappern, damit andere Teammitglieder solche Dinge entdecken können. Beachten Sie, dass es Kontroversen um Codierungsmethoden gibt, viele Beiträge dazu auf Stack Overflow (ein solcher Beitrag ) und MSDN-Blogger (wie dieser ).

public static string ToQueryString(this NameValueCollection source)
{
    return String.Join("&", source.AllKeys
        .SelectMany(key => source.GetValues(key)
            .Select(value => String.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value))))
        .ToArray());
}

Bearbeiten: mit Null-Unterstützung, obwohl Sie es wahrscheinlich an Ihre spezielle Situation anpassen müssen

public static string ToQueryString(this NameValueCollection source, bool removeEmptyEntries)
{
    return source != null ? String.Join("&", source.AllKeys
        .Where(key => !removeEmptyEntries || source.GetValues(key)
            .Where(value => !String.IsNullOrEmpty(value))
            .Any())
        .SelectMany(key => source.GetValues(key)
            .Where(value => !removeEmptyEntries || !String.IsNullOrEmpty(value))
            .Select(value => String.Format("{0}={1}", HttpUtility.UrlEncode(key), value != null ? HttpUtility.UrlEncode(value) : string.Empty)))
        .ToArray())
        : string.Empty;
}
Alfred
quelle
1
Dies schlägt fehl, wenn einer der Werte null ist
Josh Noe
Dies ist falsch, es generiert viele Abfragezeichenfolgen für jedes Schlüsselwertpaar
Gayan
@GayanRanasinghe: Was bedeutet das überhaupt?
Matti Virkkunen
22

Flurl [Offenlegung: Ich bin der Autor] unterstützt das Erstellen von Abfragezeichenfolgen über anonyme Objekte (unter anderem):

var url = "http://www.some-api.com".SetQueryParams(new
{
    api_key = ConfigurationManager.AppSettings["SomeApiKey"],
    max_results = 20,
    q = "Don't worry, I'll get encoded!"
});

Mit der optionalen Begleitbibliothek Flurl.Http können Sie HTTP-Aufrufe direkt in derselben fließenden Aufrufkette ausführen und sie zu einem vollständigen REST-Client erweitern:

T result = await "https://api.mysite.com"
    .AppendPathSegment("person")
    .SetQueryParams(new { ap_key = "my-key" })
    .WithOAuthBearerToken("MyToken")
    .PostJsonAsync(new { first_name = firstName, last_name = lastName })
    .ReceiveJson<T>();

Das vollständige Paket ist auf NuGet verfügbar:

PM> Install-Package Flurl.Http

oder nur der eigenständige URL-Builder:

PM> Install-Package Flurl

Todd Menier
quelle
20

Hier ist mein später Eintrag. Ich mochte keinen der anderen aus verschiedenen Gründen, also schrieb ich meinen eigenen.

Diese Version bietet:

  • Nur Verwendung von StringBuilder. Keine ToArray () -Aufrufe oder andere Erweiterungsmethoden. Es sieht nicht so hübsch aus wie einige der anderen Antworten, aber ich halte dies für eine Kernfunktion, daher ist Effizienz wichtiger als "fließender" "Einzeiler" -Code, der Ineffizienzen verbirgt.

  • Behandelt mehrere Werte pro Schlüssel. (Ich brauchte es nicht selbst, sondern nur um Mauricio zum Schweigen zu bringen;)

    public string ToQueryString(NameValueCollection nvc)
    {
        StringBuilder sb = new StringBuilder("?");
    
        bool first = true;
    
        foreach (string key in nvc.AllKeys)
        {
            foreach (string value in nvc.GetValues(key))
            {
                if (!first)
                {
                    sb.Append("&");
                }
    
                sb.AppendFormat("{0}={1}", Uri.EscapeDataString(key), Uri.EscapeDataString(value));
    
                first = false;
            }
        }
    
        return sb.ToString();
    }

Beispiel Verwendung

        var queryParams = new NameValueCollection()
        {
            { "x", "1" },
            { "y", "2" },
            { "foo", "bar" },
            { "foo", "baz" },
            { "special chars", "? = &" },
        };

        string url = "http://example.com/stuff" + ToQueryString(queryParams);

        Console.WriteLine(url);

Ausgabe

http://example.com/stuff?x=1&y=2&foo=bar&foo=baz&special%20chars=%3F%20%3D%20%26
DSO
quelle
Ich mag, dass dies nicht HttpUtility verwendet, das sich unter System.Web befindet und nicht überall verfügbar ist.
Kugel
+1 für die Nichtverwendung von linq und die Verwendung von HttpUtility. Ich würde ein leeres jdn erstellen und die Variable "bool first" fallen lassen und dann in der Schleife einfach sb.Append (sb.Length == 0? "?": "&") Vor dem sb.AppendFormat () haben. Wenn nvc leer ist, gibt die Methode eine leere Zeichenfolge anstelle eines einsamen "?" Zurück.
Mathew Leger
Diese Antwort behandelt einzelne Parameter mit mehreren Werten. zB? id = 1 & id = 3 & id = 2 & id = 9
Mathemats
12

Wie wäre es mit Erweiterungsmethoden, mit denen Sie die Parameter in einem fließenden Stil wie diesem hinzufügen können?

string a = "http://www.somedomain.com/somepage.html"
    .AddQueryParam("A", "TheValueOfA")
    .AddQueryParam("B", "TheValueOfB")
    .AddQueryParam("Z", "TheValueOfZ");

string b = new StringBuilder("http://www.somedomain.com/anotherpage.html")
    .AddQueryParam("A", "TheValueOfA")
    .AddQueryParam("B", "TheValueOfB")
    .AddQueryParam("Z", "TheValueOfZ")
    .ToString(); 

Hier ist die Überladung, die Folgendes verwendet string:

public static string AddQueryParam(
    this string source, string key, string value)
{
    string delim;
    if ((source == null) || !source.Contains("?"))
    {
        delim = "?";
    }
    else if (source.EndsWith("?") || source.EndsWith("&"))
    {
        delim = string.Empty;
    }
    else
    {
        delim = "&";
    }

    return source + delim + HttpUtility.UrlEncode(key)
        + "=" + HttpUtility.UrlEncode(value);
}

Und hier ist die Überlastung, die Folgendes verwendet StringBuilder:

public static StringBuilder AddQueryParam(
    this StringBuilder source, string key, string value)
{
    bool hasQuery = false;
    for (int i = 0; i < source.Length; i++)
    {
        if (source[i] == '?')
        {
            hasQuery = true;
            break;
        }
    }

    string delim;
    if (!hasQuery)
    {
        delim = "?";
    }
    else if ((source[source.Length - 1] == '?')
        || (source[source.Length - 1] == '&'))
    {
        delim = string.Empty;
    }
    else
    {
        delim = "&";
    }

    return source.Append(delim).Append(HttpUtility.UrlEncode(key))
        .Append("=").Append(HttpUtility.UrlEncode(value));
}
LukeH
quelle
: +1: für die einfache String-basierte Erweiterungsmethode. Einige der anderen Antworten können mehr Grenzfälle abdecken, aber das ist für meine Situation ausreichend, und es nicht erforderlich ist mir eine zu konstruieren NameValueCollection, HttpValueCollectionoder ein Uriersten. Vielen Dank!
Stanley G.
11

Ich musste das gleiche Problem für eine tragbare Klassenbibliothek (PCL) lösen, an der ich arbeite. In diesem Fall habe ich keinen Zugriff auf System.Web, daher kann ich ParseQueryString nicht verwenden.

Stattdessen habe ich System.Net.Http.FormUrlEncodedContentso verwendet:

var url = new UriBuilder("http://example.com");

url.Query = new FormUrlEncodedContent(new Dictionary<string,string>()
{
    {"param1", "val1"},
    {"param2", "val2"},
    {"param3", "val3"},
}).ReadAsStringAsync().Result;
Hortman
quelle
Dies ist die Technik, die ich verwende und auf die ich in einer anderen Frage verwiesen habe: http://stackoverflow.com/a/26744471/2108310 Der einzige Unterschied besteht darin, dass ich ein Array von KeyValue-Paaren verwende ... außer dass ich den Verweis auf System benötige. Net (das ist PCL verfügbar, wie Sie angegeben haben) Dies ist meiner Meinung nach der einfachste Weg, dies zu tun, ohne ein Paket eines Drittanbieters einzuschließen oder zu versuchen, ein Homebrew-Spaghetti-Durcheinander zusammen zu humpeln.
Rostow
9
    public static string ToQueryString(this Dictionary<string, string> source)
    {
        return String.Join("&", source.Select(kvp => String.Format("{0}={1}", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value))).ToArray());
    }

    public static string ToQueryString(this NameValueCollection source)
    {
        return String.Join("&", source.Cast<string>().Select(key => String.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(source[key]))).ToArray());
    }
Jay Douglass
quelle
1
Nett! Aber du brauchst das .ToArray()s nicht.
Mpen
7

Fügen Sie diese Klasse Ihrem Projekt hinzu

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

public class QueryStringBuilder
{
    private readonly List<KeyValuePair<string, object>> _list;

    public QueryStringBuilder()
    {
        _list = new List<KeyValuePair<string, object>>();
    }

    public void Add(string name, object value)
    {
        _list.Add(new KeyValuePair<string, object>(name, value));
    }

    public override string ToString()
    {
        return String.Join("&", _list.Select(kvp => String.Concat(Uri.EscapeDataString(kvp.Key), "=", Uri.EscapeDataString(kvp.Value.ToString()))));
    }
}

Und benutze es so:

var actual = new QueryStringBuilder {
    {"foo", 123},
    {"bar", "val31"},
    {"bar", "val32"}
};

actual.Add("a+b", "c+d");

actual.ToString(); // "foo=123&bar=val31&bar=val32&a%2bb=c%2bd"
Gian Marco Gherardi
quelle
Dies sollte die akzeptierte Antwort sein. funktioniert perfekt für Arrays wie "foo [] = 1, foo [] = 2" sowie für die Beibehaltung der Reihenfolge der Parameter, was übrigens sehr wichtig ist.
Soroush Falahati
6

Mein Angebot:

public static Uri AddQuery(this Uri uri, string name, string value)
{
    // this actually returns HttpValueCollection : NameValueCollection
    // which uses unicode compliant encoding on ToString()
    var query = HttpUtility.ParseQueryString(uri.Query);

    query.Add(name, value);

    var uriBuilder = new UriBuilder(uri)
    {
        Query = query.ToString()
    };

    return uriBuilder.Uri;
}

Verwendungszweck:

var uri = new Uri("http://stackoverflow.com").AddQuery("such", "method")
                                             .AddQuery("wow", "soFluent");

// http://stackoverflow.com?such=method&wow=soFluent
dav_i
quelle
Ich bevorzuge Ihren Ansatz Einfach und elegant, jedoch erfordert HttpUtility System.Web
Ody
5

Ungetestet, aber ich denke, etwas in dieser Richtung würde ganz gut funktionieren

public class QueryString
{
    private Dictionary<string,string> _Params = new Dictionary<string,string>();

    public overide ToString()
    {
        List<string> returnParams = new List<string>();

        foreach (KeyValuePair param in _Params)
        {
            returnParams.Add(String.Format("{0}={1}", param.Key, param.Value));
        }

        // return String.Format("?{0}", String.Join("&", returnParams.ToArray())); 

        // credit annakata
        return "?" + String.Join("&", returnParams.ToArray());
    }

    public void Add(string key, string value)
    {
        _Params.Add(key, HttpUtility.UrlEncode(value));
    }
}

QueryString query = new QueryString();

query.Add("param1", "value1");
query.Add("param2", "value2");

return query.ToString();
Nick Allen
quelle
schön gekapselt, aber das Format auf "? {0}" ist irgendwie unnötig teuer :)
Annakata
Der Klassenname wurde in QueryString geändert. Die Abfrage ist etwas mehrdeutig
Nick Allen
4

Eine auf einer schnellen Erweiterungsmethode basierende Version:

class Program
{
    static void Main(string[] args)
    {
        var parameters = new List<KeyValuePair<string, string>>
                             {
                                 new KeyValuePair<string, string>("A", "AValue"),
                                 new KeyValuePair<string, string>("B", "BValue")
                             };

        string output = "?" + string.Join("&", parameters.ConvertAll(param => param.ToQueryString()).ToArray());
    }
}

public static class KeyValueExtensions
{
    public static string ToQueryString(this KeyValuePair<string, string> obj)
    {
        return obj.Key + "=" + HttpUtility.UrlEncode(obj.Value);
    }
}

Sie können eine where-Klausel verwenden, um auszuwählen, welche Parameter der Zeichenfolge hinzugefügt werden.

Martin Harris
quelle
3

Angenommen, Sie möchten Abhängigkeiten zu anderen Assemblys reduzieren und die Dinge einfach halten, können Sie Folgendes tun:

var sb = new System.Text.StringBuilder();

sb.Append("a=" + HttpUtility.UrlEncode("TheValueOfA") + "&");
sb.Append("b=" + HttpUtility.UrlEncode("TheValueOfB") + "&");
sb.Append("c=" + HttpUtility.UrlEncode("TheValueOfC") + "&");
sb.Append("d=" + HttpUtility.UrlEncode("TheValueOfD") + "&");

sb.Remove(sb.Length-1, 1); // Remove the final '&'

string result = sb.ToString();

Dies funktioniert auch gut mit Schleifen. Die endgültige Entfernung des kaufmännischen Und muss außerhalb der Schleife erfolgen.

Beachten Sie, dass der Verkettungsoperator verwendet wird, um die Lesbarkeit zu verbessern. Die Kosten für die Verwendung im Vergleich zu den Kosten für die Verwendung eines StringBuilder sind minimal (ich denke, Jeff Atwood hat etwas zu diesem Thema gepostet).

Thomas Bratt
quelle
3

Kombinierte die Top-Antworten, um eine anonyme Objektversion zu erstellen :

var queryString = HttpUtility2.BuildQueryString(new
{
    key2 = "value2",
    key1 = "value1",
});

Das erzeugt dies:

Schlüssel2 = Wert2 & Schlüssel1 = Wert1

Hier ist der Code:

public static class HttpUtility2
{
    public static string BuildQueryString<T>(T obj)
    {
        var queryString = HttpUtility.ParseQueryString(string.Empty);

        foreach (var property in TypeDescriptor.GetProperties(typeof(T)).Cast<PropertyDescriptor>())
        {
            var value = (property.GetValue(obj) ?? "").ToString();
            queryString.Add(property.Name, value);
        }

        return queryString.ToString();
    }
}
Luis Perez
quelle
2

Wie akzeptierte Lösung, jedoch auf "Punkt" -LINQ-Syntax übertragen ...

private string ToQueryString(NameValueCollection nvc)
{
    if (nvc == null) return String.Empty;
    var queryParams = 
          string.Join("&", nvc.AllKeys.Select(key => 
              string.Join("&", nvc.GetValues(key).Select(v => string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(v))))));
    return "?" + queryParams;
}
Tomino
quelle
2

Ich habe eine Erweiterungsmethode für Uri , die:

  • Akzeptiert anonyme Objekte: uri.WithQuery(new { name = "value" })
  • Akzeptiert Sammlungen von string/stringPaaren (z . B. Dictionary`2 ).
  • Akzeptiert Sammlungen von string/objectPaaren (z . B. RouteValueDictionary ).
  • Akzeptiert NameValueCollection s.
  • Sortiert die Abfragewerte nach Schlüssel, sodass dieselben Werte gleiche URIs erzeugen.
  • Unterstützt mehrere Werte pro Schlüssel, wobei die ursprüngliche Reihenfolge beibehalten wird.

Die dokumentierte Version finden Sie hier .

Die Erweiterung:

public static Uri WithQuery(this Uri uri, object values)
{
    if (uri == null)
        throw new ArgumentNullException(nameof(uri));

    if (values != null)
    {
        var query = string.Join(
            "&", from p in ParseQueryValues(values)
                 where !string.IsNullOrWhiteSpace(p.Key)
                 let k = HttpUtility.UrlEncode(p.Key.Trim())
                 let v = HttpUtility.UrlEncode(p.Value)
                 orderby k
                 select string.IsNullOrEmpty(v) ? k : $"{k}={v}");

        if (query.Length != 0 || uri.Query.Length != 0)
            uri = new UriBuilder(uri) { Query = query }.Uri;
    }

    return uri;
}

Der Abfrageparser:

private static IEnumerable<KeyValuePair<string, string>> ParseQueryValues(object values)
{
    // Check if a name/value collection.
    var nvc = values as NameValueCollection;
    if (nvc != null)
        return from key in nvc.AllKeys
               from val in nvc.GetValues(key)
               select new KeyValuePair<string, string>(key, val);

    // Check if a string/string dictionary.
    var ssd = values as IEnumerable<KeyValuePair<string, string>>;
    if (ssd != null)
        return ssd;

    // Check if a string/object dictionary.
    var sod = values as IEnumerable<KeyValuePair<string, object>>;
    if (sod == null)
    {
        // Check if a non-generic dictionary.
        var ngd = values as IDictionary;
        if (ngd != null)
            sod = ngd.Cast<dynamic>().ToDictionary<dynamic, string, object>(
                p => p.Key.ToString(), p => p.Value as object);

        // Convert object properties to dictionary.
        if (sod == null)
            sod = new RouteValueDictionary(values);
    }

    // Normalize and return the values.
    return from pair in sod
           from val in pair.Value as IEnumerable<string>
            ?? new[] { pair.Value?.ToString() }
           select new KeyValuePair<string, string>(pair.Key, val);
}

Hier sind die Tests:

var uri = new Uri("https://stackoverflow.com/yo?oldKey=oldValue");

// Test with a string/string dictionary.
var q = uri.WithQuery(new Dictionary<string, string>
{
    ["k1"] = string.Empty,
    ["k2"] = null,
    ["k3"] = "v3"
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1&k2&k3=v3"));

// Test with a string/object dictionary.
q = uri.WithQuery(new Dictionary<string, object>
{
    ["k1"] = "v1",
    ["k2"] = new[] { "v2a", "v2b" },
    ["k3"] = null
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1=v1&k2=v2a&k2=v2b&k3"));

// Test with a name/value collection.
var nvc = new NameValueCollection()
{
    ["k1"] = string.Empty,
    ["k2"] = "v2a"
};

nvc.Add("k2", "v2b");

q = uri.WithQuery(nvc);
Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1&k2=v2a&k2=v2b"));

// Test with any dictionary.
q = uri.WithQuery(new Dictionary<int, HashSet<string>>
{
    [1] = new HashSet<string> { "v1" },
    [2] = new HashSet<string> { "v2a", "v2b" },
    [3] = null
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?1=v1&2=v2a&2=v2b&3"));

// Test with an anonymous object.
q = uri.WithQuery(new
{
    k1 = "v1",
    k2 = new[] { "v2a", "v2b" },
    k3 = new List<string> { "v3" },
    k4 = true,
    k5 = null as Queue<string>
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1=v1&k2=v2a&k2=v2b&k3=v3&k4=True&k5"));

// Keep existing query using a name/value collection.
nvc = HttpUtility.ParseQueryString(uri.Query);
nvc.Add("newKey", "newValue");

q = uri.WithQuery(nvc);
Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?newKey=newValue&oldKey=oldValue"));

// Merge two query objects using the RouteValueDictionary.
var an1 = new { k1 = "v1" };
var an2 = new { k2 = "v2" };

q = uri.WithQuery(
    new RouteValueDictionary(an1).Concat(
        new RouteValueDictionary(an2)));

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1=v1&k2=v2"));
Şafak Gür
quelle
2

Verkettbare Wrapper-Klasse für HttpValueCollection:

namespace System.Web.Mvc {
    public class QueryStringBuilder {
        private NameValueCollection collection;
        public QueryStringBuilder() {
            collection = System.Web.HttpUtility.ParseQueryString(string.Empty);
        }
        public QueryStringBuilder Add(string key, string value) {
            collection.Add(key, value);
            return this;
        }
        public QueryStringBuilder Remove(string key) {
            collection.Remove(key);
            return this;
        }
        public string this[string key] {
            get { return collection[key]; }
            set { collection[key] = value; }
        }
        public string ToString() {
            return collection.ToString();
        }
    }
}

Anwendungsbeispiel:

QueryStringBuilder parameters = new QueryStringBuilder()
    .Add("view", ViewBag.PageView)
    .Add("page", ViewBag.PageNumber)
    .Add("size", ViewBag.PageSize);
string queryString = parameters.ToString();
kroehre
quelle
1

Ich habe meiner PageBase-Klasse die folgende Methode hinzugefügt.

protected void Redirect(string url)
    {
        Response.Redirect(url);
    }
protected void Redirect(string url, NameValueCollection querystrings)
    {
        StringBuilder redirectUrl = new StringBuilder(url);

        if (querystrings != null)
        {
            for (int index = 0; index < querystrings.Count; index++)
            {
                if (index == 0)
                {
                    redirectUrl.Append("?");
                }

                redirectUrl.Append(querystrings.Keys[index]);
                redirectUrl.Append("=");
                redirectUrl.Append(HttpUtility.UrlEncode(querystrings[index]));

                if (index < querystrings.Count - 1)
                {
                    redirectUrl.Append("&");
                }
            }
        }

        this.Redirect(redirectUrl.ToString());
    }

Anrufen:

NameValueCollection querystrings = new NameValueCollection();    
querystrings.Add("language", "en");
querystrings.Add("id", "134");
this.Redirect("http://www.mypage.com", querystrings);
Mike Cole
quelle
1

Ich habe einige Erweiterungsmethoden geschrieben, die ich bei der Arbeit mit QueryStrings als sehr nützlich empfunden habe. Oft möchte ich mit dem aktuellen QueryString beginnen und ihn ändern, bevor ich ihn verwende. Etwas wie,

var res = Request.QueryString.Duplicate()
  .ChangeField("field1", "somevalue")
  .ChangeField("field2", "only if following is true", true)
  .ChangeField("id", id, id>0)
  .WriteLocalPathWithQuery(Request.Url)); //Uses context to write the path

Weitere Informationen und die Quelle: http://www.charlesrcook.com/archive/2008/07/23/c-extension-methods-for-asp.net-query-string-operations.aspx

Es ist einfach, aber ich mag den Stil.

ccook
quelle
1

Ich wollte nur meine 2 Cent einwerfen:

public static class HttpClientExt
{
    public static Uri AddQueryParams(this Uri uri, string query)
    {
        var ub = new UriBuilder(uri);
        ub.Query = string.IsNullOrEmpty(uri.Query) ? query : string.Join("&", uri.Query.Substring(1), query);
        return ub.Uri;
    }

    public static Uri AddQueryParams(this Uri uri, IEnumerable<string> query)
    {
        return uri.AddQueryParams(string.Join("&", query));
    } 

    public static Uri AddQueryParams(this Uri uri, string key, string value)
    {
        return uri.AddQueryParams(string.Join("=", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value)));
    }

    public static Uri AddQueryParams(this Uri uri, params KeyValuePair<string,string>[] kvps)
    {
        return uri.AddQueryParams(kvps.Select(kvp => string.Join("=", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value))));
    }

    public static Uri AddQueryParams(this Uri uri, IDictionary<string, string> kvps)
    {
        return uri.AddQueryParams(kvps.Select(kvp => string.Join("=", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value))));
    }

    public static Uri AddQueryParams(this Uri uri, NameValueCollection nvc)
    {
        return uri.AddQueryParams(nvc.AllKeys.SelectMany(nvc.GetValues, (key, value) => string.Join("=", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value))));
    }
}

Die Dokumente sagen, dass uri.Querymit einem beginnen wird? wenn es nicht leer ist, und Sie sollten es abschneiden, wenn Sie es ändern möchten.

Beachten Sie, dass HttpUtility.UrlEncodein gefunden wird System.Web.

Verwendungszweck:

var uri = new Uri("https://api.del.icio.us/v1/posts/suggest").AddQueryParam("url","http://stackoverflow.com")
mpen
quelle
1

Obwohl ich nicht elegant bin, habe ich mich für eine einfachere Version entschieden, die nicht verwendet wird NameValueCollecitons- nur ein Builder-Muster, das umwickelt ist StringBuilder.

public class UrlBuilder
{
    #region Variables / Properties

    private readonly StringBuilder _builder;

    #endregion Variables / Properties

    #region Constructor

    public UrlBuilder(string urlBase)
    {
        _builder = new StringBuilder(urlBase);
    }

    #endregion Constructor

    #region Methods

    public UrlBuilder AppendParameter(string paramName, string value)
    {
        if (_builder.ToString().Contains("?"))
            _builder.Append("&");
        else
            _builder.Append("?");

        _builder.Append(HttpUtility.UrlEncode(paramName));
        _builder.Append("=");
        _builder.Append(HttpUtility.UrlEncode(value));

        return this;
    }

    public override string ToString()
    {
        return _builder.ToString();
    }

    #endregion Methods
}

Gemäß den vorhandenen Antworten habe ich darauf geachtet, HttpUtility.UrlEncodeAnrufe zu verwenden . Es wird so verwendet:

string url = new UrlBuilder("http://www.somedomain.com/")
             .AppendParameter("a", "true")
             .AppendParameter("b", "muffin")
             .AppendParameter("c", "muffin button")
             .ToString();
// Result: http://www.somedomain.com?a=true&b=muffin&c=muffin%20button
Andrew Gray
quelle
1
// USAGE
[TestMethod]
public void TestUrlBuilder()
{
    Console.WriteLine(
        new UrlBuilder("http://www.google.com?A=B")
            .AddPath("SomePathName")
            .AddPath("AnotherPathName")
            .SetQuery("SomeQueryKey", "SomeQueryValue")
            .AlterQuery("A", x => x + "C"));
}

Ausgabe:

http://www.google.com/SomePathName/AnotherPathName?A=BC&SomeQueryKey=SomeQueryValue

Der Code; ihr könnt mir alle irgendwie irgendwo danken: D.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

// By Demetris Leptos
namespace TheOperator.Foundation.Web
{
    public class UrlBuilder
    {
        public string Scheme { get; set; }

        public string Host { get; set; }

        public int? Port { get; set; }

        public List<string> Paths { get; set; }

        public SortedDictionary<string, string> QueryPairs { get; set; }

        public UrlBuilder(string url)
        {
            this.Paths = new List<string>();
            this.QueryPairs = new SortedDictionary<string, string>();

            string path = null;
            string query = null;
            Uri relativeUri = null;
            if (!Uri.TryCreate(url, UriKind.Relative, out relativeUri))
            {
                var uriBuilder = new UriBuilder(url);
                this.Scheme = uriBuilder.Scheme;
                this.Host = uriBuilder.Host;
                this.Port = uriBuilder.Port;
                path = uriBuilder.Path;
                query = uriBuilder.Query;
            }
            else
            {
                var queryIndex = url.IndexOf('?');
                if (queryIndex >= 0)
                {
                    path = url.Substring(0, queryIndex);
                    query = url.Substring(queryIndex + 1);
                }
                else
                {
                    path = url;
                }
            }
            this.Paths.AddRange(path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries));
            if (query != null)
            {
                var queryKeyValuePairs = HttpUtility.ParseQueryString(query);
                foreach (var queryKey in queryKeyValuePairs.AllKeys)
                {
                    this.QueryPairs[queryKey] = queryKeyValuePairs[queryKey];
                }
            }
        }

        public UrlBuilder AddPath(string value)
        {
            this.Paths.Add(value);
            return this;
        }

        public UrlBuilder SetQuery(string key, string value)
        {
            this.QueryPairs[key] = value;
            return this;
        }

        public UrlBuilder RemoveQuery(string key)
        {
            this.QueryPairs.Remove(key);
            return this;
        }

        public UrlBuilder AlterQuery(string key, Func<string, string> alterMethod, bool removeOnNull = false)
        {
            string value;
            this.QueryPairs.TryGetValue(key, out value);
            value = alterMethod(value);
            if (removeOnNull && value == null)
            {
                return this.RemoveQuery(key);
            }
            else
            {
                return this.SetQuery(key, value);
            }
        }

        public override string ToString()
        {
            var path = !string.IsNullOrWhiteSpace(this.Host)
                ? string.Join("/", this.Host, string.Join("/", this.Paths))
                : string.Join("/", this.Paths);
            var query = string.Join("&", this.QueryPairs.Select(x => string.Concat(x.Key, "=", HttpUtility.UrlEncode(x.Value))));
            return string.Concat(
                !string.IsNullOrWhiteSpace(this.Scheme) ? string.Concat(this.Scheme, "://") : null,
                path,
                !string.IsNullOrWhiteSpace(query) ? string.Concat("?", query) : null);
        }
    }
}
Demetris Leptos
quelle
1

Ich habe mich für die von DSO vorgeschlagene Lösung entschieden (beantwortet am 2. August 11 um 7:29 Uhr). Für seine Lösung muss HttpUtility nicht verwendet werden. Gemäß einem Artikel in Dotnetpearls ist die Verwendung eines Wörterbuchs jedoch schneller (in Bezug auf die Leistung) als die Verwendung von NameValueCollection. Hier ist die Lösung von DSO geändert, um Dictionary anstelle von NameValueCollection zu verwenden.

    public static Dictionary<string, string> QueryParametersDictionary()
    {
        var dictionary = new Dictionary<string, string>();
        dictionary.Add("name", "John Doe");
        dictionary.Add("address.city", "Seattle");
        dictionary.Add("address.state_code", "WA");
        dictionary.Add("api_key", "5352345263456345635");

        return dictionary;
    }

    public static string ToQueryString(Dictionary<string, string> nvc)
    {
        StringBuilder sb = new StringBuilder();

        bool first = true;

        foreach (KeyValuePair<string, string> pair in nvc)
        {
                if (!first)
                {
                    sb.Append("&");
                }

                sb.AppendFormat("{0}={1}", Uri.EscapeDataString(pair.Key), Uri.EscapeDataString(pair.Value));

                first = false;
        }

        return sb.ToString();
    }
Ticus
quelle
1

Die Abfragezeichenfolge kann einer URL hinzugefügt werden durch:

  1. Erstellen Sie ein Namenswert-Erfassungsobjekt
  2. Fügen Sie diesem Objekt die Abfragezeichenfolgenelemente und ihre Werte hinzu
  3. Codieren Sie dieses Namenswert-Erfassungsobjekt in die URL, die der Code unter dem folgenden Link bereitstellt

https://blog.codingnovice.com/blog

public ActionResult Create()
{
    //declaring name value collection object
    NameValueCollection collection = new NameValueCollection();

    //adding new value to the name value collection object
    collection.Add("Id1", "wwe323");
    collection.Add("Id2", "454w");
    collection.Add("Id3", "tyt5656");
    collection.Add("Id4", "343wdsd");

    //generating query string
    string url = GenerateQueryString(collection);

    return View();
}

private string GenerateQueryString(NameValueCollection collection)
{
    var querystring = (
        from key in collection.AllKeys
        from value in collection.GetValues(key)
        select string.Format("{0}={1}",
            HttpUtility.UrlEncode(key),
            HttpUtility.UrlEncode(value))
    ).ToArray();
    return "?" + string.Join("&", querystring);
}
Job
quelle
0

Ich habe einen Helfer für mein Rasiermesserprojekt geschrieben, indem ich einige der Hinweise aus anderen Antworten verwendet habe.

Das ParseQueryString-Geschäft ist erforderlich, da wir das QueryString-Objekt der aktuellen Anforderung nicht manipulieren dürfen.

@helper GetQueryStringWithValue(string key, string value) {
    var queryString = System.Web.HttpUtility.ParseQueryString(HttpContext.Current.Request.QueryString.ToString());
    queryString[key] = value;
    @Html.Raw(queryString.ToString())
}

Ich benutze es so:

location.search = '[email protected]("var-name", "var-value")';

Wenn Sie möchten, dass es mehr als einen Wert annimmt, ändern Sie einfach die Parameter in ein Wörterbuch und fügen Sie die Paare zur Abfragezeichenfolge hinzu.

LOAS
quelle
0

Der folgende Code wird aus der HttpValueCollectionImplementierung von ToStringüber ILSpy entfernt, wodurch Sie einen Querystring für Name = Wert erhalten.

Leider ist HttpValueCollection eine interne Klasse, die Sie nur dann zurückerhalten, wenn Sie sie verwenden HttpUtility.ParseQueryString(). Ich habe alle Viewstate-Teile entfernt und es wird standardmäßig codiert:

public static class HttpExtensions
{
    public static string ToQueryString(this NameValueCollection collection)
    {
        // This is based off the NameValueCollection.ToString() implementation
        int count = collection.Count;
        if (count == 0)
            return string.Empty;

        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < count; i++)
        {
            string text = collection.GetKey(i);
            text = HttpUtility.UrlEncodeUnicode(text);
            string value = (text != null) ? (text + "=") : string.Empty;
            string[] values = collection.GetValues(i);
            if (stringBuilder.Length > 0)
            {
                stringBuilder.Append('&');
            }
            if (values == null || values.Length == 0)
            {
                stringBuilder.Append(value);
            }
            else
            {
                if (values.Length == 1)
                {
                    stringBuilder.Append(value);
                    string text2 = values[0];
                    text2 = HttpUtility.UrlEncodeUnicode(text2);
                    stringBuilder.Append(text2);
                }
                else
                {
                    for (int j = 0; j < values.Length; j++)
                    {
                        if (j > 0)
                        {
                            stringBuilder.Append('&');
                        }
                        stringBuilder.Append(value);
                        string text2 = values[j];
                        text2 = HttpUtility.UrlEncodeUnicode(text2);
                        stringBuilder.Append(text2);
                    }
                }
            }
        }

        return stringBuilder.ToString();
    }
}
Chris S.
quelle
0

Dies ist identisch mit der akzeptierten Antwort, außer dass sie etwas kompakter ist:

private string ToQueryString(NameValueCollection nvc)
{
    return "?" + string.Join("&", nvc.AllKeys.Select(k => string.Format("{0}={1}", 
        HttpUtility.UrlEncode(k), 
        HttpUtility.UrlEncode(nvc[k]))));
}
Dieser Typ
quelle
0

Nur für diejenigen, die die VB.NET-Version der Top-Antwort benötigen:

Public Function ToQueryString(nvc As System.Collections.Specialized.NameValueCollection) As String
    Dim array As String() = nvc.AllKeys.SelectMany(Function(key As String) nvc.GetValues(key), Function(key As String, value As String) String.Format("{0}={1}", System.Web.HttpUtility.UrlEncode(key), System.Web.HttpUtility.UrlEncode(value))).ToArray()
    Return "?" + String.Join("&", array)
End Function

Und die Version ohne LINQ:

Public Function ToQueryString(nvc As System.Collections.Specialized.NameValueCollection) As String
    Dim lsParams As New List(Of String)()

    For Each strKey As String In nvc.AllKeys
        Dim astrValue As String() = nvc.GetValues(strKey)

        For Each strValue As String In astrValue
            lsParams.Add(String.Format("{0}={1}", System.Web.HttpUtility.UrlEncode(strKey), System.Web.HttpUtility.UrlEncode(strValue)))
        Next ' Next strValue
    Next ' strKey
    Dim astrParams As String() = lsParams.ToArray()
    lsParams.Clear()
    lsParams = Nothing

    Return "?" + String.Join("&", astrParams)
End Function ' ToQueryString

Und die C # -Version ohne LINQ:

    public static string ToQueryString(System.Collections.Specialized.NameValueCollection nvc)
    {
        List<string> lsParams = new List<string>();

        foreach (string strKey in nvc.AllKeys)
        {
            string[] astrValue = nvc.GetValues(strKey);

            foreach (string strValue in astrValue)
            {
                lsParams.Add(string.Format("{0}={1}", System.Web.HttpUtility.UrlEncode(strKey), System.Web.HttpUtility.UrlEncode(strValue)));
            } // Next strValue

        } // Next strKey

        string[] astrParams =lsParams.ToArray();
        lsParams.Clear();
        lsParams = null;

        return "?" + string.Join("&", astrParams);
    } // End Function ToQueryString
Stefan Steiger
quelle