it-swarm.com.de

Wie testen Sie Ihre Request.QueryString [] -Variablen?

Ich benutze häufig Request.QueryString[] - Variablen.

In meinem Page_load Mache ich oft Dinge wie:

       int id = -1;

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

        DoSomethingSpectacularNow(id);

Es wirkt alles etwas klobig und unsinnig. Wie gehen Sie mit Ihren Request.QueryString[] Um?

50
inspite

Nachfolgend finden Sie eine Erweiterungsmethode, mit der Sie Code wie folgt schreiben können:

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

Es verwendet TypeDescriptor, um die Konvertierung durchzuführen. Abhängig von Ihren Anforderungen können Sie eine Überladung hinzufügen, die einen Standardwert annimmt, anstatt eine Ausnahme auszulösen:

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);
}
52
Bryan Watts

Verwenden Sie stattdessen int.TryParse, um den try-catch-Block zu entfernen:

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

Probieren Sie diesen Kerl ...

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

Dann können Sie den Kerl ganz einfach über ...

keys.Contains("someKey")
19

Ich benutze eine kleine Hilfsmethode:

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

Mit dieser Methode kann ich Werte aus der Abfragezeichenfolge folgendermaßen lesen:

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

Verwenden Sie stattdessen int.TryParse ...

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

Das setzt natürlich voraus, dass "nicht vorhanden" dasselbe Ergebnis haben sollte wie "keine ganze Zahl".

BEARBEITEN: In anderen Fällen, wenn Sie ohnehin Anforderungsparameter als Zeichenfolgen verwenden, halte ich es auf jeden Fall für eine gute Idee, deren Vorhandensein zu überprüfen.

10
Jon Skeet

Sie können auch die folgenden Erweiterungsmethoden verwenden und dies tun

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

}

// Erweiterungsmethoden

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;
}
9
terjetyl
if(!string.IsNullOrEmpty(Request.QueryString["id"]))
{
//querystring contains id
}
4
Colin Dekker

Ich habe Funktionen für jede (eigentlich ist es eine kleine Klasse mit viel Statik):

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

Wenn dies fehlschlägt, wird -1 zurückgegeben (was für mich fast immer in Ordnung ist, ich habe auch einige andere Funktionen für negative Zahlen).

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

Eeee das ist ein Karma-Risiko ...

Ich habe eine DRY unit-testable Abstraktion, weil es zu viele Querystring-Variablen gab, um sie in einer Legacy-Konvertierung beizubehalten.

Der folgende Code stammt aus einer Utility-Klasse, deren Konstruktor eine NameValueCollection-Eingabe (this.source) erfordert, und das String-Array "keys" ist darauf zurückzuführen, dass die Legacy-App eher organisch war und die Möglichkeit hatte, dass mehrere verschiedene Strings ein potenzieller Eingabeschlüssel waren. Allerdings mag ich die Erweiterbarkeit. Diese Methode überprüft die Sammlung auf den Schlüssel und gibt ihn im erforderlichen Datentyp zurück.

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

Ich habe tatsächlich eine Utility-Klasse, die Generics verwendet, um eine Sitzung zu "umbrechen", die die gesamte "Grunzarbeit" für mich erledigt. Ich habe auch etwas fast Identisches für die Arbeit mit QueryString-Werten.

Dies hilft, die Code-Dupe für die (häufig zahlreichen) Prüfungen zu entfernen.

Beispielsweise:

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

HINWEIS:

Dabei wird offensichtlich auf Statik zurückgegriffen, die einige Leute nicht mögen, weil sie sich auf Testcode auswirken kann. Sie können leicht eine Umgestaltung in etwas vornehmen, das auf Instanzen und erforderlichen Schnittstellen basiert. Ich denke, das Statik-Beispiel ist das hellste.

Hoffe das hilft/gibt Anlass zum Nachdenken.

1
Rob Cooper

Ich habe die Antwort von Bryan Watts dahingehend geändert, dass, wenn der Parameter, den Sie gefragt haben, nicht existiert und Sie einen nullfähigen Typ angegeben haben, dieser null zurückgibt:

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

Sie können dies jetzt tun:

Request.QueryString.GetValue<int?>(paramName) ?? 10;
1
W3Max