2008-12-08 9 views
49

Frecuentemente utilizo las variables Request.QueryString[].¿Cómo se evalúan las variables Request.QueryString []?

En mi Page_load hago a menudo cosas como:

 int id = -1; 

     if (Request.QueryString["id"] != null) { 
      try 
      { 
       id = int.Parse(Request.QueryString["id"]); 
      } 
      catch 
      { 
       // deal with it 
      } 
     } 

     DoSomethingSpectacularNow(id); 

Todo parece un poco torpe y basura. ¿Cómo lidias con tu Request.QueryString[] s?

Respuesta

51

A continuación se presenta un método de extensión que le permitirá escribir código como este:

int id = request.QueryString.GetValue<int>("id"); 
DateTime date = request.QueryString.GetValue<DateTime>("date"); 

Hace uso de TypeDescriptor para realizar la conversión. En función de sus necesidades, usted podría agregar una sobrecarga que tiene un valor por defecto en lugar de lanzar una excepción:

public static T GetValue<T>(this NameValueCollection collection, string key) 
{ 
    if(collection == null) 
    { 
     throw new ArgumentNullException("collection"); 
    } 

    var value = collection[key]; 

    if(value == null) 
    { 
     throw new ArgumentOutOfRangeException("key"); 
    } 

    var converter = TypeDescriptor.GetConverter(typeof(T)); 

    if(!converter.CanConvertFrom(typeof(string))) 
    { 
     throw new ArgumentException(String.Format("Cannot convert '{0}' to {1}", value, typeof(T))); 
    } 

    return (T) converter.ConvertFrom(value); 
} 
+0

Tuve que cambiar la línea 15 y 17 para hacer este trabajo: var converter = TypeDescriptor.GetConverter (typeof (T)); if (! Converter.CanConvertTo (value.GetType())) –

+0

Gracias Bryan –

+0

Hola, eso es muy bonito, pero no funciona con nullables, por ejemplo int? Puede haber un error en el convertidor de tipo? Vale la pena probar si estás interesado. – bplus

32

Uso int.TryParse en lugar de deshacerse del bloque try-catch:

if (!int.TryParse(Request.QueryString["id"], out id)) 
{ 
    // error case 
} 
+0

Gracias amigo, que es el tipo de consejo que necesitaba: D – inspite

+0

Sí, TryParse es grande! –

+0

Excelente idea ... –

10

Bien para una utilización cosa int.TryParse lugar ...

int id; 
if (!int.TryParse(Request.QueryString["id"], out id)) 
{ 
    id = -1; 
} 

Eso supone que "no presente "debería tener el mismo resultado que" no un número entero ", por supuesto.

EDITAR: En otros casos, cuando va a utilizar los parámetros de solicitud como cadenas de todos modos, creo que definitivamente es una buena idea validar que están presentes.

4
if(!string.IsNullOrEmpty(Request.QueryString["id"])) 
{ 
//querystring contains id 
} 
+0

¿Qué pasa si el usuario se equivoca como page.aspx? Id = 123 a page.aspx? 1234 –

+0

@DamienJoe Entonces el usuario debería obtener un 404. – Dan

+0

@DamienJoe: ¿Por qué el usuario estaría escribiendo la cadena de consulta? parámetros en forma manual, ¿no deberían estar haciendo clic solo en los enlaces (bien formados) que les da? –

1

que tienen funciones para cada uno (en realidad es una pequeña clase, con mucha estática):

  • GetIntegerFromQuerystring(val)
  • GetIntegerFromPost(val)
  • ....

Devuelve - 1 si falla (que casi siempre está bien para mí, tengo algunas otras funciones para números negativos también).

Dim X as Integer = GetIntegerFromQuerystring("id") 
If x = -1 Then Exit Sub 
17

estoy usando un poco de método de ayuda:

public static int QueryString(string paramName, int defaultValue) 
{ 
    int value; 
    if (!int.TryParse(Request.QueryString[paramName], out value)) 
     return defaultValue; 
    return value; 
} 

Este método me permite leer los valores de la cadena de consulta de la siguiente manera:

int id = QueryString("id", 0); 
+0

¡Qué gran idea para un método auxiliar poner en una biblioteca de clase! –

+0

Sí, me gusta también; D – inspite

+0

De hecho, hay un error dentro del método. En lugar de "Request.QueryString" debería ser "HttpContext.Current.Request.QueryString". – M4N

1

eeee esto es una riesgo de karma ...

Tengo una abstracción de DRY controlable por unidad porque, bueno, porque había demasiadas variables de cadena de consulta s para continuar en una conversión heredada.

El código siguiente es de una clase de utilidad cuyo constructor requiere una entrada NameValueCollection (this.source) y el conjunto de cadenas "keys" se debe a que la aplicación heredada era bastante orgánica y había desarrollado la posibilidad de que clave de entrada potencial Sin embargo, me gusta la extensibilidad. Este método inspecciona la colección de la clave y la devuelve en el tipo de datos requerido.

private T GetValue<T>(string[] keys) 
{ 
    return GetValue<T>(keys, default(T)); 
} 

private T GetValue<T>(string[] keys, T vDefault) 
{ 
    T x = vDefault; 

    string v = null; 

    for (int i = 0; i < keys.Length && String.IsNullOrEmpty(v); i++) 
    { 
     v = this.source[keys[i]]; 
    } 

    if (!String.IsNullOrEmpty(v)) 
    { 
     try 
     { 
      x = (typeof(T).IsSubclassOf(typeof(Enum))) ? (T)Enum.Parse(typeof(T), v) : (T)Convert.ChangeType(v, typeof(T)); 
     } 
     catch(Exception e) 
     { 
      //do whatever you want here 
     } 
    } 

    return x; 
} 
+0

Esto es más o menos lo que uso ... :) –

1

que en realidad tienen una clase de utilidad que utiliza los genéricos de "envolver" sesión, lo que hace todo el "trabajo sucio" para mí, también tengo algo casi idéntico para trabajar con valores de cadena de consulta.

Esto ayuda a eliminar el código duplicado para los controles (a menudo numerosos) ..

Por ejemplo:

public class QueryString 
{ 
    static NameValueCollection QS 
    { 
     get 
     { 
      if (HttpContext.Current == null) 
       throw new ApplicationException("No HttpContext!"); 

      return HttpContext.Current.Request.QueryString; 
     } 
    } 

    public static int Int(string key) 
    { 
     int i; 
     if (!int.TryParse(QS[key], out i)) 
      i = -1; // Obviously Change as you see fit. 
     return i; 
    } 

    // ... Other types omitted. 
} 

// And to Use.. 
void Test() 
{ 
    int i = QueryString.Int("test"); 
} 

NOTA:

Esto obviamente hace uso de la estática, que algunas personas no les gusta por la forma en que puede afectar código de prueba .. Usted puede fácilmente Refactor en algo que funciona en función de las instancias y las interfaces que requiera ... Creo que el ejemplo estático es el más ligero.

Espero que esto ayude/da lugar a la reflexión.

9

Se pueden utilizar los siguientes métodos de extensión, así y hacer como esto

int? id = Request["id"].ToInt(); 
if(id.HasValue) 
{ 

} 

métodos de extensión //

public static int? ToInt(this string input) 
{ 
    int val; 
    if (int.TryParse(input, out val)) 
     return val; 
    return null; 
} 

public static DateTime? ToDate(this string input) 
{ 
    DateTime val; 
    if (DateTime.TryParse(input, out val)) 
     return val; 
    return null; 
} 

public static decimal? ToDecimal(this string input) 
{ 
    decimal val; 
    if (decimal.TryParse(input, out val)) 
     return val; 
    return null; 
} 
+0

Esto es bastante inteligente Me gusta. Gracias – inspite

+1

Utilizamos esta técnica, pero tenemos versiones que no admiten nulos, p. "int ToInt (int defaultValue = 0)" y "int? AsInt()" – Jerph

+0

@ La sugerencia de Jerph es bastante buena, pero también puede usar lo anterior como 'Request [" id "]. ToInt(). GetValueOrDefault (0) 'para obtener el mismo efecto. –

1

he modificado respuesta Bryan Watts por lo que si el parámetro su pedir no existe y ha especificado una anulable tipo volverá nulo:

public static T GetValue<T>(this NameValueCollection collection, string key) 
    { 
     if (collection == null) 
     { 
      return default(T); 
     } 

     var value = collection[key]; 

     if (value == null) 
     { 
      return default(T); 
     } 

     var type = typeof(T); 

     if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) 
     { 
      type = Nullable.GetUnderlyingType(type); 
     } 

     var converter = TypeDescriptor.GetConverter(type); 

     if (!converter.CanConvertTo(value.GetType())) 
     { 
      return default(T); 
     } 

     return (T)converter.ConvertTo(value, type); 
    } 

ahora puede hacer esto:

Request.QueryString.GetValue<int?>(paramName) ?? 10; 
+0

'Int32Converter' no puede convertir 'System.String' a 'System.Nullable'1 [[System.Int32, mscorlib, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089]]'. – Soonts

+1

Gracias @Soonts por el comentario, cambié el código un poco para manejar Nullables. – W3Max

19

probar este tipo ...

List<string> keys = new List<string>(Request.QueryString.AllKeys); 

entonces usted será capaz de buscar el tipo de una cadena muy fácil a través de ...

keys.Contains("someKey") 
+1

Whoa. Sí. Fantástico. +1 – Brandon

+1

¡Genial! ¡Fácil, rápido y lo que necesitaba! +1 Simple es la forma en que me gusta. – Mixxiphoid

Cuestiones relacionadas