wake-up-neo.com

NameValueCollection zur URL-Abfrage?

Ich weiß ich kann das

var nv = HttpUtility.ParseQueryString(req.RawUrl);

Aber gibt es eine Möglichkeit, diese zurück in eine URL umzuwandeln?

var newUrl = HttpUtility.Something("/page", nv);
63
user34537

Wenn Sie einfach ToString() für NameValueCollection aufrufen, werden die Wertepaare in einem name1=value1&name2=value2-Abfragenzeichenfolgeformat zurückgegeben. Beachten Sie, dass NameValueCollection-Typen dies nicht wirklich unterstützen und es ist irreführend, dies zu suggerieren, aber das Verhalten funktioniert hier aufgrund des tatsächlich zurückgegebenen internen Typs, wie unten erläutert.

Vielen Dank an @mjwills für den Hinweis, dass die HttpUtility.ParseQueryString-Methode tatsächlich ein internes HttpValueCollection-Objekt und nicht einen regulären NameValueCollection zurückgibt ( , obwohl die Dokumentation NameValueCollection angibt). Der HttpValueCollection verschlüsselt den Abfragestring automatisch, wenn ToString() verwendet wird. Daher müssen Sie keine Routine schreiben, die die Auflistung durchläuft und die UrlEncode-Methode verwendet. Das gewünschte Ergebnis wird bereits zurückgegeben.

Mit dem Ergebnis in der Hand können Sie es dann an die URL anhängen und umleiten:

var nameValues = HttpUtility.ParseQueryString(Request.QueryString.ToString());
string url = Request.Url.AbsolutePath + "?" + nameValues.ToString();
Response.Redirect(url);

Momentan besteht die einzige Möglichkeit, eine Variable HttpValueCollection zu verwenden, durch Verwendung der oben gezeigten Methode ParseQueryString (mit Ausnahme der Reflexion natürlich). Es sieht so aus, als würde sich dies nicht ändern, da das Problem Connect, in dem diese Klasse öffentlich gemacht werden soll, mit dem Status "nicht behoben" geschlossen wurde. 

Nebenbei können Sie die Methoden Add, Set und Remove für nameValues aufrufen, um vor dem Anhängen eines der Elemente der Querzeichenfolge Änderungen vorzunehmen. Wenn Sie daran interessiert sind siehe meine Antwort auf eine andere Frage .

97
Ahmad Mageed
string q = String.Join("&",
             nvc.AllKeys.Select(a => a + "=" + HttpUtility.UrlEncode(nvc[a])));
61
Denis

Dies sollte ohne zu viel Code funktionieren:

NameValueCollection nameValues = HttpUtility.ParseQueryString(String.Empty);
nameValues.Add(Request.QueryString);
// modify nameValues if desired
var newUrl = "/page?" + nameValues;

Die Idee ist, HttpUtility.ParseQueryString zu verwenden, um eine leere Sammlung des Typs HttpValueCollection zu generieren. Diese Klasse ist eine Unterklasse von NameValueCollection, die als internal markiert ist, damit Ihr Code keine Instanz davon erstellen kann.

Das Schöne an HttpValueCollection ist, dass die ToString-Methode für Sie die Kodierung übernimmt. Mit der NameValueCollection.Add(NameValueCollection)-Methode können Sie die vorhandenen Abfragezeichenfolgeparameter zu Ihrem neu erstellten Objekt hinzufügen, ohne die Request.QueryString-Auflistung zuerst in eine url-codierte Zeichenfolge konvertieren und sie dann in eine Auflistung zurück analysieren zu müssen.

Diese Technik kann auch als Erweiterungsmethode verfügbar gemacht werden:

public static string ToQueryString(this NameValueCollection nameValueCollection)
{
    NameValueCollection httpValueCollection = HttpUtility.ParseQueryString(String.Empty)
    httpValueCollection.Add(nameValueCollection);
    return httpValueCollection.ToString();
}
11
dana

Erstellen Sie eine Erweiterungsmethode, die einige Schleifen verwendet. Ich bevorzuge diese Lösung, weil sie lesbar ist (keine linq), System.Web.HttpUtility nicht erfordert und doppelte Schlüssel verarbeitet.

public static string ToQueryString(this NameValueCollection nvc)
{
    if (nvc == null) return string.Empty;

    StringBuilder sb = new StringBuilder();

    foreach (string key in nvc.Keys)
    {
        if (string.IsNullOrWhiteSpace(key)) continue;

        string[] values = nvc.GetValues(key);
        if (values == null) continue;

        foreach (string value in values)
        {
            sb.Append(sb.Length == 0 ? "?" : "&");
            sb.AppendFormat("{0}={1}", Uri.EscapeDataString(key), Uri.EscapeDataString(value));
        }
    }

    return sb.ToString();
}

Beispiel

var queryParams = new NameValueCollection()
{
    { "order_id", "0000" },
    { "item_id", "1111" },
    { "item_id", "2222" },
    { null, "skip entry with null key" },
    { "needs escaping", "special chars ? = &" },
    { "skip entry with null value", null }
};

Console.WriteLine(queryParams.ToQueryString());

Ausgabe

?order_id=0000&item_id=1111&item_id=2222&needs%20escaping=special%20chars%20%3F%20%3D%20%26
11
Mathew Leger

Eigentlich sollten Sie auch den Schlüssel verschlüsseln, nicht nur den Wert.

string q = String.Join("&",
nvc.AllKeys.Select(a => $"{HttpUtility.UrlEncode(a)}={HttpUtility.UrlEncode(nvc[a])}"));
5
user2397863

Da eine Variable NameValueCollection mehrere Werte für denselben Schlüssel haben kann, sollten Sie Folgendes berücksichtigen, wenn Sie sich mit dem Format der Abfragestring befassen (da sie als durch Kommas getrennte Werte statt als "Array-Notation" zurückgegeben wird).

Beispiel

var nvc = new NameValueCollection();
nvc.Add("key1", "val1");
nvc.Add("key2", "val2");
nvc.Add("empty", null);
nvc.Add("key2", "val2b");

Wechseln Sie in: key1=val1&key2[]=val2&empty&key2[]=val2b statt key1=val1&key2=val2,val2b&empty.

Code

string qs = string.Join("&", 
    // "loop" the keys
    nvc.AllKeys.SelectMany(k => {
        // "loop" the values
        var values = nvc.GetValues(k);
        if(values == null) return new[]{ k };
        return nvc.GetValues(k).Select( (v,i) => 
            // 'gracefully' handle formatting
            // when there's 1 or more values
            string.Format(
                values.Length > 1
                    // pick your array format: k[i]=v or k[]=v, etc
                    ? "{0}[]={1}"
                    : "{0}={1}"
                , k, HttpUtility.UrlEncode(v), i)
        );
    })
);

oder wenn Sie Linq nicht so sehr mögen ...

string qs = nvc.ToQueryString(); // using...

public static class UrlExtensions {
    public static string ToQueryString(this NameValueCollection nvc) {
        return string.Join("&", nvc.GetUrlList());
    }

    public static IEnumerable<string> GetUrlList(this NameValueCollection nvc) {
        foreach(var k in nvc.AllKeys) {
            var values = nvc.GetValues(k);
            if(values == null)  { yield return k; continue; }
            for(int i = 0; i < values.Length; i++) {
                yield return
                // 'gracefully' handle formatting
                // when there's 1 or more values
                string.Format(
                    values.Length > 1
                        // pick your array format: k[i]=v or k[]=v, etc
                        ? "{0}[]={1}"
                        : "{0}={1}"
                    , k, HttpUtility.UrlEncode(values[i]), i);
            }
        }
    }
}

Wie bereits in Kommentaren dargelegt, mit Ausnahme von dieser Antwort beziehen sich die meisten anderen Antworten auf das Szenario (Request.QueryString ist eine HttpValueCollection, "nicht" eine NameValueCollection) und nicht die eigentliche Frage.

Update: adressierte Nullwertausgabe aus Kommentar.

3
drzaus

Die kurze Antwort ist, .ToString() für die NameValueCollection zu verwenden und sie mit der ursprünglichen URL zu kombinieren.

Ich möchte jedoch auf einige Dinge hinweisen:

Sie können HttpUtility.ParseQueryString nicht für Request.RawUrl verwenden. Die ParseQueryString()-Methode sucht nach einem Wert wie diesem: ?var=value&var2=value2.

Wenn Sie eine NameValueCollection der QueryString-Parameter abrufen möchten, verwenden Sie einfach Request.QueryString().

var nv = Request.QueryString;

Um die URL neu zu erstellen, verwenden Sie einfach nv.ToString ().

string url = String.Format("{0}?{1}", Request.Path, nv.ToString());

Wenn Sie versuchen, eine URL-Zeichenfolge zu analysieren, anstatt das Request-Objekt zu verwenden, verwenden Sie Uri und die HttpUtility.ParseQueryString-Methode.

Uri uri = new Uri("<THE URL>");
var nv = HttpUtility.ParseQueryString(uri.Query);
string url = String.Format("{0}?{1}", uri.AbsolutePath, nv.ToString());
3
Jeremy

In AspNet Core 2.0 können Sie die Methode QueryHelpers AddQueryString verwenden.

1
Atchitutchuk

Würde das für dich funktionieren?

public static string BuildUrl(string relativeUrl, params string[] queryString)
{
    // build queryString from string parameters
    char[] trimChars = { ' ', '&', '?' };
    StringBuilder builder = new StringBuilder();
    string sepChar = "&";
    string sep = String.Empty;
    foreach (string q in queryString)
    {
        builder.Append(sep).Append(q.Trim(trimChars));
        sep = sepChar;
    }

    if (String.IsNullOrEmpty(builder.ToString())) { return relativeUrl; }
    else { return relativeUrl + "?" + builder.ToString(); }
}

Benutzen:

string url = BuildUrl("/mypage.apsx", "qs1=a", "qs2=b", "qs3=c");
1
Brad

Wie von @Atchitutchuk vorgeschlagen, können Sie QueryHelpers.AddQueryString in ASP.NET Core verwenden:

    public string FormatParameters(NameValueCollection parameters)
    {
        var queryString = "";
        foreach (var key in parameters.AllKeys)
        {
            foreach (var value in parameters.GetValues(key))
            {
                queryString = QueryHelpers.AddQueryString(queryString, key, value);
            }
        };

        return queryString.TrimStart('?');
    }
0
arni

Ich verwende UriBuilder immer, um eine URL mit einem Abfragestring wieder in eine gültige und ordnungsgemäß codierte URL umzuwandeln.

var url = "http://my-link.com?foo=bar";

var uriBuilder = new UriBuilder(url);
var query = HttpUtility.ParseQueryString(uriBuilder.Query);
query.Add("yep", "foo&bar");

uriBuilder.Query = query.ToString();
var result = uriBuilder.ToString();

// http://my-link.com:80/?foo=bar&yep=foo%26bar
0
ms007

Sie können verwenden. 

var ur = new Uri("/page",UriKind.Relative);

wenn dieses nv vom Typ string ist, können Sie den ersten uri-Parameter anhängen 

var ur2 = new Uri("/page?"+nv.ToString(),UriKind.Relative);
0