在C#中将查询字符串转换为字典的最佳方法

80

我正在寻找将HTTP GET请求的查询字符串转换为字典形式,以及将其转回查询字符串的最简单方法。

我认为一旦查询转换成字典形式,就可以更容易地进行各种操作,但我似乎需要很多代码才能完成转换。有没有推荐的方式?

14个回答

73

HttpUtility.ParseQueryString()将查询字符串解析为NameValueCollection对象,将后者转换为IDictionary<string, string>只需要简单的foreach。然而,这可能是不必要的,因为NameValueCollection具有一个索引器,所以它的行为很像字典。


如何在URL中构建查询字符串回到:https://dev59.com/nHRA5IYBdhLWcg3wyBD1 - Rudi
16
Request.QueryString已经是一个NameValueCollection,@H70的答案最简单,可将其放入字典中 var parameters = Request.QueryString.Keys.Cast<string>().ToDictionary(k => k, v => Request.QueryString[v]); - johnny 5
我刚试着使用它,但我认为它有问题:当迭代时,生成的 NameValueCollection 值会被静默修改。例如,尝试调用 var q = HttpUtility.ParseQueryString("firstParam=cGFzc35+d29yZA==")(这是字符串 pass~~word 的 base64 编码),然后使用 for (var i = 0; i <= q.Keys.Count; ++i) { var val = q[q.Keys[i]]; } 进行迭代。观察 val 的值:你将得到 cGFzc35 d29yZA== 而不是 cGFzc35+d29yZA== - OfirD
@OfirD - 这里有一个接受编码参数的过载方法 - https://learn.microsoft.com/en-us/dotnet/api/system.web.httputility.parsequerystring?view=net-7.0#system-web-httputility-parsequerystring(system-string-system-text-encoding) - Ashish Agrawal

45

这是我通常的做法

Dictionary<string, string> parameters = HttpContext.Current.Request.QueryString.Keys.Cast<string>()
    .ToDictionary(k => k, v => HttpContext.Current.Request.QueryString[v]);

简单明了!值得一加1 :-) - Matt
只返回翻译文本。为了优雅的答案 - mzonerz
3
请注意,键可以为null,这会导致语句执行失败。我通过将“.ToDictionary(k => k,…”更改为“.ToDictionary(k => k ?? "", …”来修复它。(您可以使用任何默认值作为“k”)。 - BoCoKeith

22

20

和Sean一样,但使用Linq(并且有一个您可以复制并粘贴的函数):

public static Dictionary<string, string> ParseQueryString(string queryString)
{
   var nvc = HttpUtility.ParseQueryString(queryString);
   return nvc.AllKeys.ToDictionary(k => k, k => nvc[k]);
}

另外,问题是如何将它转换回查询字符串:

public static string CreateQueryString(Dictionary<string, string> parameters)
{
   return string.Join("&", parameters.Select(kvp => 
      string.Format("{0}={1}", kvp.Key, HttpUtility.UrlEncode(kvp.Value))));
}

12

刚刚不得不为了一个兼容Mono的解决方案而这样做

Regex.Matches(queryString, "([^?=&]+)(=([^&]*))?").Cast<Match>().ToDictionary(x => x.Groups[1].Value, x => x.Groups[3].Value)

同样适用于Windows Phone 8(HttpUtility.ParseQueryString在那里也不存在)。 - JWL
@BinaryWorrier 如果它们不是简单的.GroupBy(x => x.Groups[1].Value).ToDictionary(g => g.Key, g => g.First().Groups[3].Value); 将可以工作(有明显的数据丢失)。 - Drakarah
这个答案对我来说非常完美,因为我正在Unity中编写C#代码。有点惊讶在那个环境下找到一个解决方案是如此困难,但没关系。 - jhocking
顺便提一下,这段代码依赖于“System.Linq”和“System.Text.RegularExpressions;”。 - jhocking

10
在ASP.NET Core中,请使用ParseQuery
var query = HttpContext.Request.QueryString.Value;
var queryDictionary = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(query);

7
我喜欢Jon Canning的答案的简洁性,但为了多样性,这里提供另一种替代方案,也适用于像Windows Phone 8这样缺少HttpUtility.ParseQueryString()实用程序的受限环境:
    public static Dictionary<string, string> ParseQueryString(String query)
    {
        Dictionary<String, String> queryDict = new Dictionary<string, string>();
        foreach (String token in query.TrimStart(new char[] { '?' }).Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries))
        {
            string[] parts = token.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length == 2)
                queryDict[parts[0].Trim()] = HttpUtility.UrlDecode(parts[1]).Trim();
            else
                queryDict[parts[0].Trim()] = "";
        }
        return queryDict;
    }

实际上,对于Canning的答案进行有用的改进,可以处理解码url编码的值(就像上面的解决方案中一样):
    public static Dictionary<string, string> ParseQueryString2(String query)
    {
       return Regex.Matches(query, "([^?=&]+)(=([^&]*))?").Cast<Match>().ToDictionary(x => x.Groups[1].Value, x => HttpUtility.UrlDecode( x.Groups[3].Value ));
    }

7
没有使用HttpUtility的一行代码
var dictionary = query.Replace("?", "").Split('&').ToDictionary(x => x.Split('=')[0], x => x.Split('=')[1]);

好的,我没有考虑到那种情况。你可以在 .ToDictionary 前添加 .Where(x => !String.IsNullOrEmpty(x)) 来避免异常。 - vicentedealencar
你可以简单地在.Split('&')中添加一个StringSplitOptions.RemoveEmptyEntries参数:.Split(new [] { '&' }, StringSplitOptions.RemoveEmptyEntries) - Rezgar Cadro

6
另一种做法如下:

NameValueCollection nvcData = HttpUtility.ParseQueryString(queryString);
Dictionary<string, string> dictData = new Dictionary<string, string>(nvcData.Count);
foreach (string key in nvcData.AllKeys)
{
    dictData.Add(key, nvcData.Get(key));
}

1

最简单的:

Dictionary<string, string> parameters = new Dictionary<string, string>();

for (int i = 0; i < context.Request.QueryString.Count; i++)
{
    parameters.Add(context.Request.QueryString.GetKey(i), context.Request.QueryString[i]);
}

为您的代码段添加描述,仅有代码块是不够的。 - Mathews Sunny

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