2009-03-18 17 views
167

Mam ciąg znaków w .NET, który jest w rzeczywistości adresem URL. Chcę łatwy sposób uzyskać wartość z określonego parametru.Uzyskaj parametry adresu URL z ciągu znaków w .NET

Zwykle używam tylko Request.Params["theThingIWant"], ale ten ciąg nie pochodzi z żądania. Mogę utworzyć nowy Uri element tak:

Uri myUri = new Uri(TheStringUrlIWantMyValueFrom); 

mogę używać myUri.Query uzyskać ciąg kwerendy ... ale potem widocznie musiał znaleźć jakiś sposób regexy dzieląc go.

Czy brakuje mi czegoś oczywistego, czy też nie ma czegoś takiego, jak to zrobić, tworząc coś w rodzaju regexu?

Odpowiedz

361

Zastosowanie statyczne ParseQueryString metoda System.Web.HttpUtility klasy, która zwraca NameValueCollection.

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

Sprawdź dokumentację na http://msdn.microsoft.com/en-us/library/ms150046.aspx

+11

To nie wydaje się wykrywać pierwszego parametru. np. parsowanie "http://www.google.com/search?q=energy+edge&rls=com.microsoft:en-au&ie=UTF-8&oe=UTF-8&startIndex=&startPage=1" nie wykrywa parametru q –

+0

@ Andrew Potwierdzam. To dziwne (błąd?). Mimo to nadal używasz 'HttpUtility.ParseQueryString (myUri.Query) .Get (0)' i wyodrębni pierwszy parametr. ' –

+0

Dowolne narzędzie .NET do zbudowania sparametryzowanego adresu URL zapytania? – Shimmy

11

Wygląda na to, że powinieneś zapętlić wartości myUri.Query i przeanalizować je stamtąd.

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

Nie użyłbym tego kodu bez testowania go na kilku zniekształconych adresach URL. To może złamać na niektóre/wszystkie z nich:

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

Korzystanie .NET Reflector aby metodę System.Web.HttpValueCollectionFillFromString. To daje kod, który ASP.NET używa do wypełnienia kolekcji Request.QueryString.

34

To jest chyba to, co chcesz

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"); 
+0

Bardzo kompaktowy i użyteczny –

9

@Andrew i @CZFox

miałem ten sam problem i znaleźć przyczynę się, że parametr jeden jest w rzeczywistości: http://www.example.com?param1 i nie param1 który jest czego można oczekiwać.

Usunięcie wszystkich znaków przed znacznikiem zapytania włącznie z tym znakiem rozwiązuje ten problem.Tak w istocie funkcja HttpUtility.ParseQueryString wymaga jedynie ważny parametr ciągu zapytania zawierającego tylko znaki po znaku zapytania na przykład:

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

Moja obejście:

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");` 
+0

Po utworzeniu instancji URI pojawia się błąd "Nieprawidłowy identyfikator URI: nie można określić formatu identyfikatora URI." Nie sądzę, aby to rozwiązanie działało zgodnie z zamierzeniami. –

+0

@PaulMatthews, masz rację. W czasie tego rozwiązania korzystałem ze starszej platformy .net 2.0. Aby potwierdzić, twoje oświadczenie, skopiowałem i wkleiłem to rozwiązanie do LINQPad v2 przez Josepha Albahara i otrzymałem ten sam błąd, o którym wspomniałeś. –

+0

@PaulMatthews, Aby naprawić, usuń linię, która czyta Uri myUri = new Uri (RawUrl); i po prostu przekazać RawUrl do ostatniej instrukcji w postaci: string param1 = HttpUtility.ParseQueryString (RawUrl) .Get ("param2"); –

2

Można użyć następującego obejścia go do pracy z pierwszego parametru tOO:

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

Oto kolejna alternatywa, jeżeli z jakiegoś powodu, nie mogą lub nie chcą korzystać HttpUtility.ParseQueryString().

Jest zbudowany tak, aby był nieco tolerancyjny dla "zniekształconych" łańcuchów zapytań, tzn. http://test/test.html?empty= staje się parametrem z pustą wartością. W razie potrzeby dzwoniący może zweryfikować parametry.

test

[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); 
     } 
    } 
} 
+1

wygląda na to, że zapomniałeś, że zapytanie może zawierać zduplikowane wartości (np.g: wielokrotny wybór) – Dementic

+0

Dzięki, masz rację. Zmieniłem to. – alsed42

0

jeśli chcesz się dostać QueryString na stronie domyślnej .Default strona oznacza bieżącej strony URL. można wypróbować ten kod:

string paramIl = HttpUtility.ParseQueryString(this.ClientQueryString).Get("city"); 
1
HttpContext.Current.Request.QueryString.Get("id"); 
+0

jak tego użyć z ciągiem –

1

Albo jeśli nie znać adres URL (tak aby uniknąć hardcoding użyj AbsoluteUri

Przykład ...

 //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; 
     } 
-2

Użyłem go i działa idealnie

<%=Request.QueryString["id"] %> 
+1

z ciągu łańcuchowego nie zapytania –

Powiązane problemy