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?

Beska
quelle

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

CZFox
quelle
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");
Sergej Andrejev
quelle
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);
        }
    }
}
alsed42
quelle
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" );`
Mo Gauvin
quelle
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
Tom Ritter
quelle
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");
tomsv
quelle
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 .

David
quelle
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;
        }
Fandango68
quelle
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");
Erhan Demirci
quelle
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();
        } 
Ralle12
quelle
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
        }
Indy411
quelle
-1
HttpContext.Current.Request.QueryString.Get("id");
Hallgeir Engen
quelle
1
wie man dies mit einer Schnur benutzt
Arun Prasad ES
-4

Ich habe es benutzt und es läuft perfekt

<%=Request.QueryString["id"] %>
Hoang Huynh Nhat
quelle
2
von einem String nicht Abfrage String
Arun Prasad ES