Ruft URL-Parameter von einer Zeichenfolge in .NET ab


239

Ich habe eine Zeichenfolge in .NET, die eigentlich eine URL ist. Ich möchte einen einfachen Weg, um den Wert von einem bestimmten Parameter zu erhalten.

Normalerweise würde ich nur verwenden Request.Params["theThingIWant"], aber diese Zeichenfolge stammt nicht aus der Anforderung. Ich kann einen neuen UriArtikel wie folgt erstellen :

Uri myUri = new Uri(TheStringUrlIWantMyValueFrom);

Ich kann verwenden myUri.Query, um die Abfragezeichenfolge abzurufen ... aber dann muss ich anscheinend eine reguläre Methode finden, um sie aufzuteilen.

Vermisse ich etwas Offensichtliches oder gibt es keine eingebaute Möglichkeit, dies zu tun, ohne eine Art regulären Ausdruck usw. zu erstellen?

Antworten:


494

Verwenden Sie die statische ParseQueryStringMethode der System.Web.HttpUtilityKlasse, die zurückgibt NameValueCollection.

Uri myUri = new Uri("http://www.example.com?param1=good&param2=bad");
string param1 = HttpUtility.ParseQueryString(myUri.Query).Get("param1");

Überprüfen Sie die Dokumentation unter http://msdn.microsoft.com/en-us/library/ms150046.aspx


14
Dies scheint den ersten Parameter nicht zu erkennen. Zum Beispiel erkennt das Parsen von " google.com/… " den Parameter q nicht
Andrew Shepherd

@ Andrew Ich bestätige. Es ist seltsam (Fehler?). Sie können es aber immer noch verwenden HttpUtility.ParseQueryString(myUri.Query).Get(0)und es wird den ersten Parameter extrahieren. `
Mariusz Pawelski

Gibt es ein .NET-Tool zum Erstellen einer parametrisierten Abfrage-URL?
Shimmy Weitzhandler

6
Sie können keine vollständigen Abfrage-URLs mit analysieren HttpUtility.ParseQueryString(string)! Wie der Name schon sagt, werden Abfragezeichenfolgen analysiert, keine URLs mit Abfrageparametern. Wenn Sie dies tun möchten, müssen Sie es zuerst folgendermaßen aufteilen ?: Url.Split('?')und das letzte Element mithilfe von (je nach Situation und Bedarf) [0]oder LINQs Last()/ abrufen LastOrDefault().
Kosiek

1
Wenn ich dies selbst ausprobiere, scheint sich die Signatur wie folgt geändert zu haben: HttpUtility.ParseQueryString (uri.Query) .GetValues ​​("param1"). First ()
The Senator

48

Dies ist wahrscheinlich was Sie wollen

var uri = new Uri("http://domain.test/Default.aspx?var1=true&var2=test&var3=3");
var query = HttpUtility.ParseQueryString(uri.Query);

var var2 = query.Get("var2");

34

Hier ist eine weitere Alternative, wenn Sie sie aus irgendeinem Grund nicht verwenden können oder wollen HttpUtility.ParseQueryString().

Dies ist so konstruiert, dass es gegenüber "fehlerhaften" Abfragezeichenfolgen etwas tolerant ist, dh es http://test/test.html?empty=wird ein Parameter mit einem leeren Wert. Der Anrufer kann die Parameter bei Bedarf überprüfen.

public static class UriHelper
{
    public static Dictionary<string, string> DecodeQueryParameters(this Uri uri)
    {
        if (uri == null)
            throw new ArgumentNullException("uri");

        if (uri.Query.Length == 0)
            return new Dictionary<string, string>();

        return uri.Query.TrimStart('?')
                        .Split(new[] { '&', ';' }, StringSplitOptions.RemoveEmptyEntries)
                        .Select(parameter => parameter.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries))
                        .GroupBy(parts => parts[0],
                                 parts => parts.Length > 2 ? string.Join("=", parts, 1, parts.Length - 1) : (parts.Length > 1 ? parts[1] : ""))
                        .ToDictionary(grouping => grouping.Key,
                                      grouping => string.Join(",", grouping));
    }
}

Prüfung

[TestClass]
public class UriHelperTest
{
    [TestMethod]
    public void DecodeQueryParameters()
    {
        DecodeQueryParametersTest("http://test/test.html", new Dictionary<string, string>());
        DecodeQueryParametersTest("http://test/test.html?", new Dictionary<string, string>());
        DecodeQueryParametersTest("http://test/test.html?key=bla/blub.xml", new Dictionary<string, string> { { "key", "bla/blub.xml" } });
        DecodeQueryParametersTest("http://test/test.html?eins=1&zwei=2", new Dictionary<string, string> { { "eins", "1" }, { "zwei", "2" } });
        DecodeQueryParametersTest("http://test/test.html?empty", new Dictionary<string, string> { { "empty", "" } });
        DecodeQueryParametersTest("http://test/test.html?empty=", new Dictionary<string, string> { { "empty", "" } });
        DecodeQueryParametersTest("http://test/test.html?key=1&", new Dictionary<string, string> { { "key", "1" } });
        DecodeQueryParametersTest("http://test/test.html?key=value?&b=c", new Dictionary<string, string> { { "key", "value?" }, { "b", "c" } });
        DecodeQueryParametersTest("http://test/test.html?key=value=what", new Dictionary<string, string> { { "key", "value=what" } });
        DecodeQueryParametersTest("http://www.google.com/search?q=energy+edge&rls=com.microsoft:en-au&ie=UTF-8&oe=UTF-8&startIndex=&startPage=1%22",
            new Dictionary<string, string>
            {
                { "q", "energy+edge" },
                { "rls", "com.microsoft:en-au" },
                { "ie", "UTF-8" },
                { "oe", "UTF-8" },
                { "startIndex", "" },
                { "startPage", "1%22" },
            });
        DecodeQueryParametersTest("http://test/test.html?key=value;key=anotherValue", new Dictionary<string, string> { { "key", "value,anotherValue" } });
    }

    private static void DecodeQueryParametersTest(string uri, Dictionary<string, string> expected)
    {
        Dictionary<string, string> parameters = new Uri(uri).DecodeQueryParameters();
        Assert.AreEqual(expected.Count, parameters.Count, "Wrong parameter count. Uri: {0}", uri);
        foreach (var key in expected.Keys)
        {
            Assert.IsTrue(parameters.ContainsKey(key), "Missing parameter key {0}. Uri: {1}", key, uri);
            Assert.AreEqual(expected[key], parameters[key], "Wrong parameter value for {0}. Uri: {1}", parameters[key], uri);
        }
    }
}

hilfreich für Xamarin-Projekt, wo HttpUtility nicht verfügbar ist
Artemious

12

@ Andrew und @ CZFox

Ich hatte den gleichen Fehler und fand die Ursache darin, dass der Parameter eins tatsächlich ist: http://www.example.com?param1und nicht param1, was man erwarten würde.

Durch Entfernen aller Zeichen vor und einschließlich des Fragezeichens wird dieses Problem behoben. Im Wesentlichen HttpUtility.ParseQueryStringerfordert die Funktion nur einen gültigen Abfragezeichenfolgenparameter, der nur Zeichen nach dem Fragezeichen enthält, wie in:

HttpUtility.ParseQueryString ( "param1=good&param2=bad" )

Meine Problemumgehung:

string RawUrl = "http://www.example.com?param1=good&param2=bad";
int index = RawUrl.IndexOf ( "?" );
if ( index > 0 )
    RawUrl = RawUrl.Substring ( index ).Remove ( 0, 1 );

Uri myUri = new Uri( RawUrl, UriKind.RelativeOrAbsolute);
string param1 = HttpUtility.ParseQueryString( myUri.Query ).Get( "param1" );`

Wenn der URI instanziiert wird, wird die Fehlermeldung "Ungültiger URI: Das Format des URI konnte nicht ermittelt werden." Angezeigt. Ich denke nicht, dass diese Lösung wie beabsichtigt funktioniert.
Paul Matthews

@ PaulMatthews, du bist richtig. Zum Zeitpunkt dieser Lösung verwendete ich das ältere .net Framework 2.0. Um Ihre Aussage zu bestätigen, habe ich diese Lösung von Joseph Albahara kopiert und in LINQPad v2 eingefügt und den gleichen Fehler erhalten, den Sie erwähnt haben.
Mo Gauvin

@PaulMatthews, Um dies zu beheben, entfernen Sie die Zeile mit der Aufschrift Uri myUri = new Uri (RawUrl); und übergeben Sie RawUrl lediglich an die letzte Anweisung wie in: string param1 = HttpUtility.ParseQueryString (RawUrl) .Get ("param2");
Mo Gauvin

Ja, die Tatsache, dass nur der Teil der Abfragezeichenfolge analysiert wird, steht im Namen und in der Dokumentation. Es ist kein Fehler. Ich bin mir nicht mal sicher, wie sie es klarer machen könnten. ParseQueryStringanalysiert Abfragezeichenfolgen.
PandaWood

12

Sieht so aus, als sollten Sie die Werte von myUri.Querydurchlaufen und von dort aus analysieren.

 string desiredValue;
 foreach(string item in myUri.Query.Split('&'))
 {
     string[] parts = item.Replace("?", "").Split('=');
     if(parts[0] == "desiredKey")
     {
         desiredValue = parts[1];
         break;
     }
 }

Ich würde diesen Code jedoch nicht verwenden, ohne ihn auf einer Reihe von fehlerhaften URLs zu testen. Es könnte bei einigen / allen dieser Probleme auftreten:

  • hello.html?
  • hello.html?valuelesskey
  • hello.html?key=value=hi
  • hello.html?hi=value?&b=c
  • etc

4

Sie können die folgende Problemumgehung verwenden, um auch mit dem ersten Parameter zu arbeiten:

var param1 =
    HttpUtility.ParseQueryString(url.Substring(
        new []{0, url.IndexOf('?')}.Max()
    )).Get("param1");

2

Verwenden Sie .NET Reflector, um die FillFromStringMethode von anzuzeigen System.Web.HttpValueCollection. Dadurch erhalten Sie den Code, mit dem ASP.NET die Request.QueryStringSammlung füllt .


1

Oder wenn Sie die URL nicht kennen (um Hardcodierung zu vermeiden, verwenden Sie die AbsoluteUri

Beispiel ...

        //get the full URL
        Uri myUri = new Uri(Request.Url.AbsoluteUri);
        //get any parameters
        string strStatus = HttpUtility.ParseQueryString(myUri.Query).Get("status");
        string strMsg = HttpUtility.ParseQueryString(myUri.Query).Get("message");
        switch (strStatus.ToUpper())
        {
            case "OK":
                webMessageBox.Show("EMAILS SENT!");
                break;
            case "ER":
                webMessageBox.Show("EMAILS SENT, BUT ... " + strMsg);
                break;
        }

0

Wenn Sie möchten, dass Ihr QueryString auf der Standardseite angezeigt wird. Die Standardseite bezeichnet Ihre aktuelle Seiten-URL. Sie können diesen Code ausprobieren:

string paramIl = HttpUtility.ParseQueryString(this.ClientQueryString).Get("city");

0

Das ist eigentlich sehr einfach und das hat bei mir funktioniert :)

        if (id == "DK")
        {
            string longurl = "selectServer.aspx?country=";
            var uriBuilder = new UriBuilder(longurl);
            var query = HttpUtility.ParseQueryString(uriBuilder.Query);
            query["country"] = "DK";

            uriBuilder.Query = query.ToString();
            longurl = uriBuilder.ToString();
        } 

0

Für alle, die alle Abfragezeichenfolgen einer Zeichenfolge durchlaufen möchten

        foreach (var item in new Uri(urlString).Query.TrimStart('?').Split('&'))
        {
            var subStrings = item.Split('=');

            var key = subStrings[0];
            var value = subStrings[1];

            // do something with values
        }


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.