2009-03-02 6 views
21

Tengo curiosidad por lo que todos hacen por manejar/abstraer el QueryString en ASP.NET. En algunas de nuestras aplicaciones web que veo un montón de esto en todo el sitio:Conversión/acceso a los valores de QueryString en ASP.NET

int val = 0; 
if(Request.QueryString["someKey"] != null) 
{ 
val = Convert.ToInt32(Request.QueryString["someKey"]); 
} 

¿Cuáles son algunas formas mejores de manejar esta grosería?

Respuesta

24

me suelen gustar la idea de abstraer como propiedades. Por ejemplo:

 public int age { 
     get 
     { 
      if (Request.QueryString["Age"] == null) 
       return 0; 
      else 
       return int.Parse(Request.QueryString["Age"]);          
     } 
    } 

Se podría añadir más de validación si se quería. Pero tiendo a gustar envolver todas mis variables de cadena de consulta de esta manera.

EDITAR: --- También como otro cartel señaló que debe crear estas propiedades en cada página. Mi respuesta es no, no. Puede crear estas propiedades en una sola clase que puede llamar "QueryStrings" o algo así. A continuación, puede crear una instancia de esta clase en cada página en la que desea acceder a sus cadenas de consulta, a continuación, sólo tiene que hacer algo como

var queryStrings = new QueryStrings(); 
var age = queryStrings.age; 

esta manera se puede encapsular toda la lógica de acceso y manejo de cada tipo de variable de consulta en una única ubicación de mantenimiento.

EDIT2: --- Y debido a que es una instancia de la clase, también puede usar la inyección de dependencia para inyectar la clase QueryStrings en cada lugar que lo esté utilizando. StructureMap hace un buen trabajo de eso. Esto también le permite simular la clase QueryStrings e inyectarla si desea realizar pruebas automáticas de unidades. Es mucho más fácil simular esto que el objeto Request de ASP.Net.

+0

La bonificación adicional aquí es que le dice a los desarrolladores futuros exactamente qué esperar de la cadena de consulta cuando se sientan por primera vez con su código. –

+0

Sí, gracias por notar eso. Esa es definitivamente la intención. – 7wp

+0

+1 - una gran manera de manejarlo – nailitdown

8

Una cosa es que no está capturando valores en blanco aquí. Es posible que tenga una url como "http://example.com?someKey=&anotherKey=12345" y en este caso el valor del parámetro "someKey" es "" (vacío). Puede usar string.IsNullOrEmpty() para verificar estados nulos y vacíos.

También cambiaría "someKey" para almacenar en una variable. De esta forma no estás repitiendo cadenas literales en múltiples lugares. Lo hace más fácil de mantener.

int val = 0; 
string myKey = "someKey"; 
if (!string.IsNullOrEmpty(Request.QueryString[myKey])) 
{ 
    val = int.Parse(Request.QueryString[myKey]); 
} 

Espero que ayude!

Ian

+0

¡es probable que arroje una excepción! –

+0

seguramente querrá incluir el manejo de errores. Eso es un hecho, ¿no? :) –

+0

'int val = 0; cadena myKey = "someKey"; cadena strVal = HttpContext.Current.Request.QueryString [myKey]; if (! String.IsNullOrEmpty (strVal) &&! Int.TryParse (strVal, out val)) { val = 0; } ' – GFoley83

3

Escribir una especie de un método de ayuda (biblioteca) para manejarlo ...

public static void GetInt(this NameValueCollection nvCol, string key, out int keyValue, int defaultValue) 
{ 
    if (string.IsNullOrEmpty(nvCol[key]) || !int.TryParse(nvCol[key], out keyValue)) 
     keyValue = defaultValue; 
} 

O algo por el estilo ...

+0

Pero el programador debería saber el tipo esperado en el que se debe devolver la cadena de consulta. (Para saber a qué función llamar) Si lo envuelve usando un captador de propiedades como en la respuesta que di, entonces todo lo que debería saber es el nombre de la propiedad que está buscando. Intellisense hará el resto. – 7wp

+0

Sí, al igual que el programador tendría que saber el tipo esperado de la cadena de consulta para configurar una propiedad. Mi solución es detener las repetidas afirmaciones "si" repetidas en todo el programa como se describe en la pregunta. Lo que hacen con el código después depende de ellos - ¡ojalá, póngalo en una propiedad! – Charlino

+0

pero una vez que la propiedad está configurada, eso está hecho.otros programadores que vengan después no tendrán que adivinar qué tipo de datos hay en la cadena de consulta y qué validación específica debería ocurrir. puedes envolver todo eso en la propiedad. – 7wp

1

que hemos estado usando para mantener constantes todos estos llaves "sueltos" en una ubicación central:

public class Constants 
{ 
    public class QueryString 
    { 
    public const string PostID = "pid"; 
    public const string PostKey = "key"; 
    } 
    public class Cookie 
    { 
    public const string UserID = "mydomain.com-userid"; 
    } 
    public class Cache 
    { 
    public const string PagedPostList = "PagedPostList-{0}-{1}"; 
    } 
    public class Context 
    { 
    public const string PostID = "PostID"; 
    } 
    public class Security 
    { 
    public const RoleAdministrator = "Administrator"; 
    } 
} 

de esta manera, se accede fácilmente a las constantes que necesita con:

public void Index() 
{ 
    if (Request[Constants.QueryString.PostKey] == "eduncan911") 
    { 
    // do something 
    } 
} 

public object GetPostsFromCache(int postID, int userID) 
{ 
    String cacheKey = String.Format(
     Constants.Cache.PagedPostList 
     , userID 
     , postID); 
    return Cache[cacheKey] as IList<Post>; 
} 
0

Estoy con el afiche que me sugirió los métodos de ayuda (comentaría sobre él, pero todavía no puedo). Alguien más no estuvo de acuerdo con él a favor de la creación de propiedades, pero mi respuesta a eso es que no maneja con gracia el problema de verificar valores nulos o no válidos, etc. Si tiene métodos de ayuda, toda esa lógica se puede escribir una vez y centralizado

Si tiene muchas páginas, agregar propiedades para cada una puede consumir más tiempo de lo que vale. Pero eso es obviamente solo una preferencia, por lo que cada uno es suyo.

Una cosa interesante que podría mejorar en el otro método de ayuda del póster es convertir el parámetro out en un parámetro de referencia (cambiar a ref). De esta forma, puede establecer un valor predeterminado para la propiedad, en caso de que no se pase. A veces puede desear parámetros opcionales, por ejemplo, entonces puede hacer que comience con un valor predeterminado para aquellos casos en los que el parámetro opcional no se pasa explícitamente (más fácil que tener un valor predeterminado pasado por separado). Incluso puede agregar un parámetro booleano IsRequired al final y hacer que arroje una excepción si el bool se establece en verdadero y el parámetro no se pasa. Eso puede ser útil en muchos casos.

+0

No tiene que crear las propiedades en cada página. Solo una clase con todas las propiedades que espera usar. A continuación, puede crear una instancia de esa clase en las páginas donde lo está utilizando para acceder a los parámetros de consulta. – 7wp

+0

Bueno, eso supone que tienes los mismos parámetros de cadena de consulta en cada página. En un sistema grande, vas a tener una gran cantidad de diferentes, igual que tienes diferentes parámetros para diferentes métodos. Parece que la consistencia es algo bueno. – x4000

3

Esto es lo que se me ocurrió. Utiliza los genéricos para devolver un valor inflexible de tipos de la cadena de consulta o un valor predeterminado opcional si el parámetro no está en la cadena de consulta:

/// <summary> 
    /// Gets the given querystring parameter as a the specified value <see cref="Type"/> 
    /// </summary> 
    /// <typeparam name="T">The type to convert the querystring value to</typeparam> 
    /// <param name="name">Querystring parameter name</param> 
    /// <param name="defaultValue">Default value to return if parameter not found</param> 
    /// <returns>The value as the specified <see cref="Type"/>, or the default value if not found</returns> 
    public static T GetValueFromQueryString<T>(string name, T defaultValue) where T : struct 
    { 
     if (String.IsNullOrEmpty(name) || HttpContext.Current == null || HttpContext.Current.Request == null) 
      return defaultValue; 

     try 
     { 
      return (T)Convert.ChangeType(HttpContext.Current.Request.QueryString[name], typeof(T)); 
     } 
     catch 
     { 
      return defaultValue; 
     } 
    } 

    /// <summary> 
    /// Gets the given querystring parameter as a the specified value <see cref="Type"/> 
    /// </summary> 
    /// <typeparam name="T">The type to convert the querystring value to</typeparam> 
    /// <param name="name">Querystring parameter name</param> 
    /// <returns>The value as the specified <see cref="Type"/>, or the types default value if not found</returns> 
    public static T GetValueFromQueryString<T>(string name) where T : struct 
    { 
     return GetValueFromQueryString(name, default(T)); 
    } 

Después de haber escrito este post que he escrito una pequeña biblioteca de clases para manipular los valores de cadena de consulta - ver https://github.com/DanDiplo/QueryString-Helper

+0

+1 para un buen uso simple de genéricos. – GFoley83

+0

Obteniendo: 'El tipo 'cadena' debe ser un tipo de valor que no admite nulos para usarlo como parámetro 'T' en el genérico ...' –

+0

@PierreLebon Las cadenas son tipos de valores, por lo que la restricción genérica struct no con ellos. Pero no necesita convertirlos, ya que el valor ya es una cadena. Desde esta publicación escribí una pequeña biblioteca, vea https://github.com/DanDiplo/QueryString-Helper, eso debería ayudarlo. –

1

Según yo, la mejor manera de obtener el valor cadena de consulta es como siguiente:
Si no se encuentra la cadena de consulta entonces el valor de val será 0.

int val = 0; 
int.TryParse(Request.QueryString["someKey"], out val); 
Cuestiones relacionadas