2009-03-18 25 views
167

Tengo una cadena en .NET que en realidad es una url. Quiero una manera fácil de obtener el valor de un parámetro en particular.Obtener los parámetros url de una cadena en .NET

Normalmente, usaría Request.Params["theThingIWant"], pero esta cadena no es de la solicitud. Puedo crear un nuevo elemento Uri así:

Uri myUri = new Uri(TheStringUrlIWantMyValueFrom); 

puedo usar myUri.Query para obtener la secuencia de la pregunta ... pero entonces aparentemente no tienen que encontrar alguna manera regexy de dividirlo.

¿Me falta algo obvio, o no hay una forma incorporada de hacer esto sin crear una expresión regular de algún tipo, etc.?

Respuesta

361

Uso estática ParseQueryString método de System.Web.HttpUtility clase que devuelve NameValueCollection.

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

Comprobar la documentación en http://msdn.microsoft.com/en-us/library/ms150046.aspx

+11

Esto no parece detectar el primer parámetro. por ejemplo, al analizar "http://www.google.com/search?q=energy+edge&rls=com.microsoft:en-au&ie=UTF-8&oe=UTF-8&startIndex=&startPage=1" no se detecta el parámetro q –

+0

@ Andrew Confirmo. Es extraño (¿error?). Sin embargo, todavía puede usar 'HttpUtility.ParseQueryString (myUri.Query) .Get (0)' y extraerá el primer parámetro. ' –

+0

Cualquier herramienta .NET para construir una URL de consulta parametrizada? – Shimmy

11

Parece que debe recorrer los valores de myUri.Query y analizarlo desde allí.

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

Sin embargo, no utilizaría este código sin probarlo en un montón de URL malformadas. Podría romper en algunos/todos ellos:

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

Uso .NET Reflector para ver el método de System.Web.HttpValueCollectionFillFromString. Eso le proporciona el código que ASP.NET está utilizando para completar la colección Request.QueryString.

34

Esto es probablemente lo que quiere

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

Gracias muy compacto y útil –

9

@ Andrew y @CZFox

que tenía el mismo error y se encontró que la causa es que el parámetro uno es, de hecho: http://www.example.com?param1 y no param1 que es lo que uno esperaría

Eliminando todos los caracteres antes e incluyendo el signo de interrogación corrige este problema.Así que, en esencia, la función HttpUtility.ParseQueryString sólo requiere un parámetro de cadena de consulta válida que contiene sólo caracteres después del signo de interrogación como en:

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

Mi solución:

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

Cuando se crea una instancia del URI recibo el error "URI no válido: no se pudo determinar el formato del URI". No creo que esta solución funcione como se esperaba. –

+0

@PaulMatthews, estás en lo cierto. En el momento de esta solución, estaba usando el más antiguo .NET Framework 2.0. Para confirmar su afirmación, copié y pegué esta solución en LINQPad v2 de Joseph Albahara y recibí el mismo error que usted mencionó. –

+0

@PaulMatthews, Para solucionarlo, elimine la línea que dice Uri myUri = new Uri (RawUrl); y simplemente pasa RawUrl a la última instrucción como en: string param1 = HttpUtility.ParseQueryString (RawUrl) .Get ("param2"); –

2

Usted puede utilizar la siguiente solución para que funcione con el primer parámetro también:

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

Aquí es otra alternativa si, por cualquier razón, no puede o no desea utilizar HttpUtility.ParseQueryString().

Esto está diseñado para ser algo tolerante con las cadenas de consulta "malformadas", es decir, http://test/test.html?empty= se convierte en un parámetro con un valor vacío. El que llama puede verificar los parámetros si es necesario.

prueba

[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

parece que olvidaste que una cadena de consulta puede contener valores duplicados (p.g: selección múltiple) – Dementic

+0

Gracias, tienes razón. Lo cambie. – alsed42

0

si quieres en conseguir su cadena de consulta en la página por defecto .Default página significa que su URL de la página actual. puede probar este código:

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

cómo usar esto con una cadena –

1

O si no conoce la dirección URL (a fin de evitar hardcoding, utilice el Ejemplo AbsoluteUri

...

 //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

Lo usé y funciona perfectamente

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

desde una cadena que no es una cadena de consulta –

Cuestiones relacionadas