C# ASP.NET 查询字符串解析器

7
如果您一直在寻找一种漂亮而干净的方法来解析查询字符串值,我已经想到了这个方法:
    /// <summary>
    /// Parses the query string and returns a valid value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="key">The query string key.</param>
    /// <param name="value">The value.</param>
    protected internal T ParseQueryStringValue<T>(string key, string value)
    {
        if (!string.IsNullOrEmpty(value))
        {
            //TODO: Map other common QueryString parameters type ...
            if (typeof(T) == typeof(string))
            {
                return (T)Convert.ChangeType(value, typeof(T));
            }
            if (typeof(T) == typeof(int))
            {
                int tempValue;
                if (!int.TryParse(value, out tempValue))
                {
                    throw new ApplicationException(string.Format("Invalid QueryString parameter {0}. The value " +
                                                              "'{1}' is not a valid {2} type.", key, value, "int"));
                }
                return (T)Convert.ChangeType(tempValue, typeof(T));
            }
            if (typeof(T) == typeof(DateTime))
            {
                DateTime tempValue;
                if (!DateTime.TryParse(value, out tempValue))
                {
                    throw new ApplicationException(string.Format("Invalid QueryString parameter {0}. The value " +
                                                         "'{1}' is not a valid {2} type.", key, value, "DateTime"));
                }
                return (T)Convert.ChangeType(tempValue, typeof(T));
            }
        }
        return default(T);
    }

我一直想要这样的东西,最终终于搞定了...至少我是这么认为的...

代码应该是自解释的...

欢迎提出任何意见或建议以使其更好。


也许你在代码堆栈的更高层处理它,但请记住,在查询字符串中,一个键可以有多个值,例如 x=1,2,3。 - jro
@jro 我认为多个值的情况是无效的,因为就查询字符串而言,它只有一个值,即字符串"1,2,3",将其解析为其他任何内容都是不正确的。 - rtpHarry
7个回答

34

如果你不想进行类型转换,解析的简单方法是:

 HttpUtility.ParseQueryString(queryString);

您可以使用以下代码从URL中提取查询字符串:

 new Uri(url).Query

4
仅当网址为完整网址时,此方法才有效。如果您有相对网址,则 Uri 的查询成员不受支持。 - jrwren

5
考虑到只有三种不同的类型,我建议使用三种不同的方法 - 通用方法最好与每个类型参数都很好地配合,这是由类型约束所允许的。
此外,我强烈建议针对int和DateTime指定要使用的文化 - 这实际上不应该取决于服务器所在的文化。 (如果您有代码来猜测用户的文化,则可以使用它。)最后,我还建议支持一组明确定义的DateTime格式,而不仅仅是默认情况下TryParse支持的格式。(我基本上始终使用ParseExact / TryParseExact,而不是Parse / TryParse。)
请注意,字符串版本实际上不需要做任何事情,因为value已经是一个字符串(尽管您当前的代码将“”转换为null,这可能是您想要的,也可能不是)。

+1 对于 ParseExact/TryParseExact 特别有用,因为你可以传递一个格式数组。 - Richard

3
我已经编写了以下方法来解析 QueryString 为强类型值:

我已经编写了以下方法来解析 QueryString 为强类型值:

public static bool TryGetValue<T>(string key, out T value, IFormatProvider provider)
{
    string queryStringValue = HttpContext.Current.Request.QueryString[key];

    if (queryStringValue != null)
    {
        // Value is found, try to change the type
        try
        {
            value = (T)Convert.ChangeType(queryStringValue, typeof(T), provider);
            return true;
        }
        catch
        {
            // Type could not be changed
        }
    }

    // Value is not found, return default
    value = default(T);
    return false;
}

使用示例:

int productId = 0;
bool success = TryGetValue<int>("ProductId", out productId, CultureInfo.CurrentCulture);

对于查询字符串?productId=5bool值为真,int productId将等于5。
对于查询字符串?productId=hellobool值为假,int productId将等于0。
对于查询字符串?noProductId=notIncludedbool值为假,int productId将等于0。

2
在我的应用程序中,我一直在使用以下函数:-
public static class WebUtil
{
    public static T GetValue<T>(string key, StateBag stateBag, T defaultValue)
    {
        object o = stateBag[key];

        return o == null ? defaultValue : (T)o;
    }
}

如果未提供参数,则返回所需的默认值,类型从defaultValue中推断出来,必要时引发转换异常。
使用方法如下:
var foo = WebUtil.GetValue("foo", ViewState, default(int?));

2
这是一个旧的答案,但我已经采取了以下措施:
string queryString = relayState.Split("?").ElementAt(1);
NameValueCollection nvc = HttpUtility.ParseQueryString(queryString);

1

我觉得你做了很多不必要的类型转换。tempValue变量已经是你想要返回的类型了。同样,在字符串情况下,值已经是一个字符串,所以只需返回它即可。


0

基于Ronalds答案,我已经更新了自己的查询字符串解析方法。 我使用它的方式是将其添加为Page对象上的扩展方法,以便于我检查查询字符串值和类型,并在页面请求无效时重定向。

扩展方法如下:

public static class PageHelpers
{
    public static void RequireOrPermanentRedirect<T>(this System.Web.UI.Page page, string QueryStringKey, string RedirectUrl)
    {
        string QueryStringValue = page.Request.QueryString[QueryStringKey];

        if(String.IsNullOrEmpty(QueryStringValue))
        {
            page.Response.RedirectPermanent(RedirectUrl);
        }

        try
        {
            T value = (T)Convert.ChangeType(QueryStringValue, typeof(T));
        }
        catch
        {
            page.Response.RedirectPermanent(RedirectUrl);
        }
    }
}

这让我能够做以下事情:
protected void Page_Load(object sender, EventArgs e)
{
    Page.RequireOrPermanentRedirect<int>("CategoryId", "/");
}

我可以编写我的其余代码,并依赖于查询字符串项的存在和正确格式,这样每次访问它时就不必测试它。

注意:如果您使用的是 .net 4 之前的版本,则还需要以下 RedirectPermanent 扩展方法:

public static class HttpResponseHelpers
{
    public static void RedirectPermanent(this System.Web.HttpResponse response, string uri)
    {
        response.StatusCode = 301;
        response.StatusDescription = "Moved Permanently";
        response.AddHeader("Location", uri);
        response.End();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接