50

我经常使用Request.QueryString[]变量。

在我的Page_load我经常做这样的事情:

       int id = -1;

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

        DoSomethingSpectacularNow(id);

这一切似乎有点笨拙和垃圾。你怎么处理你Request.QueryString[]的s?

4

11 回答 11

52

下面是一个扩展方法,可让您编写如下代码:

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

TypeDescriptor用于执行转换。根据您的需要,您可以添加一个采用默认值而不是引发异常的重载:

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);
}
于 2008-12-08T15:11:00.677 回答
34

使用 int.TryParse 代替 try-catch 块:

if (!int.TryParse(Request.QueryString["id"], out id))
{
  // error case
}
于 2008-12-08T14:42:01.360 回答
19

试试这哥们...

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

然后,您将能够通过...轻松搜索该人的字符串...

keys.Contains("someKey")
于 2010-09-29T19:52:43.993 回答
17

我正在使用一个小助手方法:

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

此方法允许我通过以下方式从查询字符串中读取值:

int id = QueryString("id", 0);
于 2008-12-08T14:50:23.137 回答
10

好吧,一方面使用 int.TryParse 代替......

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

这假设“不存在”当然应该与“非整数”具有相同的结果。

编辑:在其他情况下,当您无论如何要将请求参数用作字符串时,我认为验证它们是否存在绝对是一个好主意。

于 2008-12-08T14:43:01.840 回答
9

您也可以使用下面的扩展方法并这样做

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

}

// 扩展方法

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;
}
于 2008-12-08T14:58:24.947 回答
4
if(!string.IsNullOrEmpty(Request.QueryString["id"]))
{
//querystring contains id
}
于 2008-12-08T14:44:52.150 回答
1

我确实有每个功能(实际上它是一个小类,有很多静态):

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

如果失败,它会返回 -1(这对我来说几乎总是可以的,我还有一些其他的负数函数)。

Dim X as Integer = GetIntegerFromQuerystring("id")
If x = -1 Then Exit Sub
于 2008-12-08T14:49:19.440 回答
1

Eeee 这是一个业力风险......

我有一个 DRY 可单元测试的抽象,因为有太多的查询字符串变量无法在遗留转换中继续使用。

下面的代码来自一个实用程序类,它的构造函数需要一个 NameValueCollection 输入 (this.source),而字符串数组“keys”是因为旧版应用程序相当有机,并且已经开发出将几个不同的字符串作为潜在输入键的可能性。但是我有点喜欢可扩展性。此方法检查集合中的键并以所需的数据类型返回它。

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;
}
于 2008-12-08T14:54:00.540 回答
1

我实际上有一个实用程序类,它使用泛型来“包装”会话,它为我完成了所有的“繁重的工作”,我也有一些几乎相同的东西用于处理 QueryString 值。

这有助于消除(通常很多)检查的代码重复。

例如:

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

笔记:

这显然使用了静态,有些人不喜欢它,因为它会影响测试代码。您可以轻松地重构为基于实例和您需要的任何接口的东西。我只是认为静态示例是最轻的。

希望这有助于/提供思考。

于 2008-12-08T14:57:17.803 回答
1

我修改了 Bryan Watts 的答案,以便如果您要求的参数不存在并且您指定了一个可为空的类型,它将返回 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);
    }

您现在可以这样做:

Request.QueryString.GetValue<int?>(paramName) ?? 10;
于 2009-10-19T19:00:00.663 回答