Pregunta

Con frecuencia utilizo Request.QueryString[] variables.

En mi Page_load a menudo hago 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 manejas tus <=> s?

¿Fue útil?

Solución

A continuación se muestra 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");

Utiliza TypeDescriptor para realizar la conversión. Según sus necesidades, puede agregar una sobrecarga que tome un valor predeterminado en lugar de generar 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);
}

Otros consejos

Use int. tryParse en su lugar para deshacerse del bloque try-catch:

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

Prueba este tipo ...

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

Entonces podrás buscar al chico por una cadena realmente fácil a través de ...

keys.Contains("someKey")

Estoy usando un pequeño método auxiliar:

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 valores de la cadena de consulta de la siguiente manera:

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

Bueno, para empezar, usa int. TryParse en su 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 entero &"; por supuesto.

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

También puede usar los siguientes métodos de extensión y hacer 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;
}
if(!string.IsNullOrEmpty(Request.QueryString["id"]))
{
//querystring contains id
}

Eeee, esto es un riesgo de karma ...

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

El siguiente código es de una clase de utilidad cuyo constructor requiere una entrada NameValueCollection (this.source) y la matriz de cadenas " keys " es porque la aplicación heredada era bastante orgánica y había desarrollado la posibilidad de que varias cadenas diferentes fueran una clave de entrada potencial. Sin embargo, me gusta la extensibilidad. Este método inspecciona la colección para 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;
}

De hecho, tengo una clase de utilidad que usa Genéricos para " wrap " sesión, que hace todo el " trabajo gruñido " para mí, también tengo algo casi idéntico para trabajar con los valores de QueryString.

Esto ayuda a eliminar el código duplicado para las (a menudo numerosas) comprobaciones ...

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 :

Obviamente, esto hace uso de estadísticas, que a algunas personas no les gusta debido a la forma en que puede afectar el código de prueba. Puede refactorizar fácilmente en algo que funcione en función de las instancias y las interfaces que necesite. Simplemente creo que el El ejemplo estático es el más ligero.

Espero que esto ayude / dé para pensar.

Tengo funciones para cada uno (en realidad es una clase pequeña, con muchas estadísticas):

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

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

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

Modifiqué la respuesta de Bryan Watts para que si el parámetro su pregunta no existe y ha especificado un tipo anulable, devolverá 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;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top