web-dev-qa-db-de.com

Analysieren und ändern Sie eine Abfragezeichenfolge in .NET Core

Ich habe einen absoluten URI erhalten, der eine Abfragezeichenfolge enthält. Ich möchte sicher einen Wert an die Abfragezeichenfolge anhängen und einen vorhandenen Parameter ändern.

Ich würde es vorziehen, nicht auf &foo=bar, oder verwenden Sie reguläre Ausdrücke, URI-Escape ist schwierig. Eher möchte ich einen eingebauten Mechanismus verwenden, von dem ich weiß, dass er dies korrekt macht und die Flucht behandelt.

Ich habe gefundenaton Antworten, die alle HttpUtility verwenden. Da es sich jedoch um ASP.NET Core handelt, gibt es keine System.Web-Assembly mehr und somit auch kein HttpUtility.

Was ist die geeignete Methode, um dies in ASP.NET Core zu tun, während die Core-Laufzeit angestrebt wird?

92
vcsjones

Wenn Sie ASP.NET Core 1 oder 2 verwenden, können Sie dies mit Microsoft.AspNetCore.WebUtilities.QueryHelpers Im Paket Microsoft.AspNetCore.WebUtilities tun.

Wenn Sie ASP.NET Core 3.0 oder höher verwenden, ist WebUtilities jetzt Teil des ASP.NET SDK und erfordert keine separate Nuget-Paketreferenz.

So analysieren Sie es in ein Wörterbuch:

var uri = new Uri(context.RedirectUri);
var queryDictionary = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query);

Beachten Sie, dass dies im Gegensatz zu ParseQueryString in System.Web ein Wörterbuch vom Typ IDictionary<string, string[]> In ASP.NET Core 1.x oder IDictionary<string, StringValues> In ASP.NET Core 2.x zurückgibt oder höher, der Wert ist also eine Sammlung von Zeichenfolgen. Auf diese Weise behandelt das Wörterbuch mehrere Abfragezeichenfolgenparameter mit demselben Namen.

Wenn Sie der Abfragezeichenfolge einen Parameter hinzufügen möchten, können Sie eine andere Methode für QueryHelpers verwenden:

var parametersToAdd = new System.Collections.Generic.Dictionary<string, string> { { "resource", "foo" } };
var someUrl = "http://www.google.com";
var newUri = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString(someUrl, parametersToAdd);

Mit .NET Core 2.2 können Sie die Abfragezeichenfolge mit abrufen

var request = HttpContext.Request;
var query = request.query;
foreach (var item in query){
   Debug.WriteLine(item) 
}

Sie erhalten eine Sammlung von Schlüssel-Wert-Paaren - so

[0] {[companyName, ]}
[1] {[shop, ]}
[2] {[breath, ]}
[3] {[hand, ]}
[4] {[eye, ]}
[5] {[firstAid, ]}
[6] {[eyeCleaner, ]}
119
vcsjones

Der einfachste und intuitivste Weg, einen absoluten URI zu nehmen und seine Abfragezeichenfolge nur mit ASP.NET Core-Paketen zu bearbeiten, ist in wenigen Schritten zu bewerkstelligen:

Installieren Sie Pakete

PM> Installationspaket Microsoft.AspNetCore.WebUtilities
PM> Installationspaket Microsoft.AspNetCore.Http.Extensions

Wichtige Klassen

Um sie darauf hinzuweisen, hier sind die beiden wichtigen Klassen, die wir verwenden: QueryHelpers , StringValues , QueryBuilder .

Der Code

// Raw URI including query string with multiple parameters
var rawurl = "https://bencull.com/some/path?key1=val1&key2=val2&key2=valdouble&key3=";

// Parse URI, and grab everything except the query string.
var uri = new Uri(rawurl);
var baseUri = uri.GetComponents(UriComponents.Scheme | UriComponents.Host | UriComponents.Port | UriComponents.Path, UriFormat.UriEscaped);

// Grab just the query string part
var query = QueryHelpers.ParseQuery(uri.Query);

// Convert the StringValues into a list of KeyValue Pairs to make it easier to manipulate
var items = query.SelectMany(x => x.Value, (col, value) => new KeyValuePair<string, string>(col.Key, value)).ToList();

// At this point you can remove items if you want
items.RemoveAll(x => x.Key == "key3"); // Remove all values for key
items.RemoveAll(x => x.Key == "key2" && x.Value == "val2"); // Remove specific value for key

// Use the QueryBuilder to add in new items in a safe way (handles multiples and empty values)
var qb = new QueryBuilder(items);
qb.Add("nonce", "testingnonce");
qb.Add("payerId", "pyr_");

// Reconstruct the original URL with new query string
var fullUri = baseUri + qb.ToQueryString();

Um über Änderungen auf dem Laufenden zu bleiben, kannst du meinen Blog-Beitrag hier lesen: http://benjii.me/2017/04/parse-modify-query-strings-asp-net-core/

26
Ben Cull

HttpRequest hat eine Query -Eigenschaft, die die analysierte Abfragezeichenfolge über die IReadableStringCollection -Schnittstelle verfügbar macht:

/// <summary>
/// Gets the query value collection parsed from owin.RequestQueryString.
/// </summary>
/// <returns>The query value collection parsed from owin.RequestQueryString.</returns>
public abstract IReadableStringCollection Query { get; }

Diese Diskussion auf GitHub weist ebenfalls darauf hin.

17
Yuval Itzchakov

Diese Funktion gibt Dictionary<string, string> Zurück und verwendet aus Kompatibilitätsgründen nicht Microsoft.xxx

Akzeptiert die Parameterkodierung auf beiden Seiten

Akzeptiert doppelte Schlüssel (letzten Wert zurückgeben)

var rawurl = "https://emp.com/some/path?key1.name=a%20line%20with%3D&key2=val2&key2=valdouble&key3=&key%204=44#book1";
var uri = new Uri(rawurl);
Dictionary<string, string> queryString = ParseQueryString(uri.Query);

// queryString return:
// key1.name, a line with=
// key2, valdouble
// key3, 
// key 4, 44

public Dictionary<string, string> ParseQueryString(string requestQueryString)
{
    Dictionary<string, string> rc = new Dictionary<string, string>();
    string[] ar1 = requestQueryString.Split(new char[] { '&', '?' });
    foreach (string row in ar1)
    {
        if (string.IsNullOrEmpty(row)) continue;
        int index = row.IndexOf('=');
        if (index < 0) continue;
        rc[Uri.UnescapeDataString(row.Substring(0, index))] = Uri.UnescapeDataString(row.Substring(index + 1)); // use Unescape only parts          
     }
     return rc;
}
9
Wagner Pereira

Es ist wichtig zu beachten, dass in der Zeit, seit die Top-Antwort als korrekt markiert wurde, Microsoft.AspNetCore.WebUtilities hat ein Hauptversionsupdate (von 1.x.x auf 2.x.x).

Das heißt, wenn Sie bauen gegen netcoreapp1.1 Sie müssen Folgendes ausführen, um die neueste unterstützte Version zu installieren 1.1.2:

Install-Package Microsoft.AspNetCore.WebUtilities -Version 1.1.2

1
pim

Ich benutze dies als Erweiterungsmethode, funktioniert mit einer beliebigen Anzahl von Parametern:

public static string AddOrReplaceQueryParameter(this HttpContext c, params string[] nameValues)
    {
        if (nameValues.Length%2!=0)
        {
            throw new Exception("nameValues: has more parameters then values or more values then parameters");
        }
        var qps = new Dictionary<string, StringValues>();
        for (int i = 0; i < nameValues.Length; i+=2)
        {
            qps.Add(nameValues[i], nameValues[i + 1]);
        }
        return c.AddOrReplaceQueryParameters(qps);
    }

public static string AddOrReplaceQueryParameters(this HttpContext c, Dictionary<string,StringValues> pvs)
    {
        var request = c.Request;
        UriBuilder uriBuilder = new UriBuilder
        {
            Scheme = request.Scheme,
            Host = request.Host.Host,
            Port = request.Host.Port ?? 0,
            Path = request.Path.ToString(),
            Query = request.QueryString.ToString()
        };

        var queryParams = QueryHelpers.ParseQuery(uriBuilder.Query);

        foreach (var (p,v) in pvs)
        {
            queryParams.Remove(p);
            queryParams.Add(p, v);
        }

        uriBuilder.Query = "";
        var allQPs = queryParams.ToDictionary(k => k.Key, k => k.Value.ToString());
        var url = QueryHelpers.AddQueryString(uriBuilder.ToString(),allQPs);

        return url;
    }

Nächste und vorherige Links zum Beispiel in einer Ansicht:

var next = Context.Request.HttpContext.AddOrReplaceQueryParameter("page",Model.PageIndex+1+"");

var prev = Context.Request.HttpContext.AddOrReplaceQueryParameter("page",Model.PageIndex-1+"");
1
Gabriel Luca