Question

Je me sers souvent de Request.QueryString[] variables.

Dans mon Page_load je fais souvent des choses comme:

       int id = -1;

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

        DoSomethingSpectacularNow(id);

Tout cela semble un peu maladroit et nul. Comment gérez-vous vos <=> s?

Était-ce utile?

La solution

Ci-dessous une méthode d'extension qui vous permettra d'écrire du code comme celui-ci:

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

Il utilise TypeDescriptor pour effectuer la conversion. Selon vos besoins, vous pouvez ajouter une surcharge qui prend une valeur par défaut au lieu de lancer une exception:

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);
}

Autres conseils

Utilisez plutôt int.TryParse pour supprimer le bloc try-catch:

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

Essayez ce mec ...

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

Ensuite, vous serez en mesure de rechercher le type pour une chaîne très facile via ...

keys.Contains("someKey")

J'utilise une petite méthode d'assistance:

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

Cette méthode me permet de lire les valeurs de la chaîne de requête de la manière suivante:

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

Bien, utilisez int.TryParse à la place ...

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

Cela suppose que & "pas présent &"; devrait avoir le même résultat que & "; pas un entier &"; bien sûr.

EDIT: Dans d’autres cas, quand vous utiliserez des paramètres de requête comme des chaînes, je pense que c’est une bonne idée de valider leur présence.

Vous pouvez également utiliser les méthodes d'extension ci-dessous et le faire comme ceci

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

}

// Méthodes d'extension

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 c'est un risque de karma ...

J'ai une abstraction testable sur l'unité DRY car, eh bien, car il y avait trop de variables de chaîne de requête à conserver dans une conversion héritée.

Le code ci-dessous provient d'une classe d'utilitaire dont le constructeur nécessite une entrée NameValueCollection (this.source) et le tableau de chaînes " clés " C’est parce que l’application existante était plutôt organique et qu’elle avait développé la possibilité que plusieurs chaînes soient une clé d’entrée potentielle. Cependant, j'aime bien l'extensibilité. Cette méthode inspecte la collection pour la clé et la renvoie dans le type de données requis.

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

J'ai en fait une classe d'utilitaires qui utilise Generics pour & "; emballer &"; session, qui effectue tout le " travail saccadé " pour moi, j’ai aussi quelque chose de presque identique pour travailler avec les valeurs QueryString.

Cela permet de supprimer le code dupe pour les vérifications (souvent nombreuses).

Par exemple:

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");
}

REMARQUE:

Cela utilise évidemment la statique, ce que certaines personnes n'aiment pas à cause de l'impact qu'elle peut avoir sur le code de test. Vous pouvez facilement refactoriser quelque chose qui fonctionne en fonction d'instances et d'interfaces de votre choix .. Je pense que le L’exemple statique est le plus léger.

J'espère que cela aide / donne matière à réflexion.

J'ai des fonctions pour chacun (en fait c'est une petite classe, avec beaucoup de statique):

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

Il renvoie -1 en cas d'échec ( qui me convient presque toujours, j'ai également d'autres fonctions pour les nombres négatifs ).

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

J'ai modifié la réponse de Bryan Watts de sorte que si le paramètre que vous demandez n'existe pas et que vous avez spécifié un type nullable, il retournera la valeur null:

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);
    }

Vous pouvez maintenant faire ceci:

Request.QueryString.GetValue<int?>(paramName) ?? 10;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top