如何将查询字符串解析为 .NET 中的 NameValueCollection
Posted
技术标签:
【中文标题】如何将查询字符串解析为 .NET 中的 NameValueCollection【英文标题】:How to parse a query string into a NameValueCollection in .NET 【发布时间】:2010-09-09 06:39:50 【问题描述】:我想将p1=6&p2=7&p3=8
等字符串解析为NameValueCollection
。
当您无法访问 Page.Request
对象时,最优雅的方法是什么?
【问题讨论】:
【参考方案1】:为此有一个内置的 .NET 实用程序:HttpUtility.ParseQueryString
// C#
NameValueCollection qscoll = HttpUtility.ParseQueryString(querystring);
' VB.NET
Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring)
您可能需要将querystring
替换为new Uri(fullUrl).Query
。
【讨论】:
Omar,它在 ASP.NET 4 上对我不起作用,它返回的键是“***.com?para”而不是“para”。所以我正在使用 HttpUtility.ParseQueryString(new Uri(fullUrl).Query) 这对我来说是正确的。 qscoll["p1"] , qscoll["p2"] 和 qscoll["p3"] ParseQueryString 在桌面应用程序中使用真的很糟糕,因为它不包含在客户端配置文件中;为什么要在客户端计算机上安装 100 M 的附加库以仅使用一种简单的方法?但是,微软似乎没有更好的主意。唯一的方法是实现自己的方法或使用开源实现。 VASoftOnline:在这种情况下,您可以使用 ParseQueryString 的 Mono 实现:github.com/mono/mono/blob/master/mcs/class/System.Web/… 的许可证是 MIT X11:github.com/mono/mono/blob/master/LICENSEHttpUtility.ParseQueryString
是我的建议,但在 HttpUtility.ParseQueryString("&X=1&X=2&X=3")
的情况下,结果是 ....X=1,2,3...
具有多个同名参数并不常见,但需要支持控制器参数,例如 int[] , IEnumerableHttpUtility.ParseQueryString 只要您在 Web 应用程序中或不介意包含对 System.Web 的依赖项,就可以工作。另一种方法是:
NameValueCollection queryParameters = new NameValueCollection();
string[] querySegments = queryString.Split('&');
foreach(string segment in querySegments)
string[] parts = segment.Split('=');
if (parts.Length > 0)
string key = parts[0].Trim(new char[] '?', ' ' );
string val = parts[1].Trim();
queryParameters.Add(key, val);
【讨论】:
你应该检查parts.Length > 1,以确保你可以调用parts[1] 如果没有价值怎么办?例如查询字符串可能类似于?foo=1&bar
。 HttpUtility
会将其解析为 key = null, value = "bar"
与 HttpUtility.ParseQueryString 相比,这很棒,因为它不解码值(因此保留了 base64 编码值)
实际上,您仍然需要允许值 '=' 例如 &code=A0SYw34Hj/m++lH0s7r0l/yg6GWdymzSCbI2zOn3V4o= 将删除最后一个 '=' 字符。我重写了您的部分代码以获取“=”的第一个索引并将键和值子串化以解决此问题(而不是使用拆分)。
还有很多极端情况,这里没有介绍。【参考方案3】:
由于接受的答案依赖于System.Web,许多答案都提供了自定义示例。从Microsoft.AspNet.WebApi.Client NuGet 包中有一个UriExtensions.ParseQueryString,也可以使用该方法:
var uri = new Uri("https://***.com/a/22167748?p1=6&p2=7&p3=8");
NameValueCollection query = uri.ParseQueryString();
因此,如果您想避免 System.Web 依赖并且不想自己滚动,这是一个不错的选择。
【讨论】:
相同的函数作为扩展存在于 System.Net.Http 命名空间中(见下面我的回答),不需要另一个完整的依赖... @jvenema 从哪里添加 System.Net.Http.Formatting 依赖项,我相信它只是通过添加 Microsoft.AspNet.WebApi.Client NuGet 包提供的。 必须添加一个全新的 nuget 包作为依赖项有点疯狂,尤其是一个名称中包含 AspNet 的包,它闻起来只打算部署在服务器中(在我的情况下我需要这个用于移动/桌面 Xamarin 应用程序...)【参考方案4】:我想删除对 System.Web 的依赖,以便我可以解析 ClickOnce 部署的查询字符串,同时将先决条件限制为“仅限客户端的框架子集”。
我喜欢 rp 的回答。我添加了一些额外的逻辑。
public static NameValueCollection ParseQueryString(string s)
NameValueCollection nvc = new NameValueCollection();
// remove anything other than query string from url
if(s.Contains("?"))
s = s.Substring(s.IndexOf('?') + 1);
foreach (string vp in Regex.Split(s, "&"))
string[] singlePair = Regex.Split(vp, "=");
if (singlePair.Length == 2)
nvc.Add(singlePair[0], singlePair[1]);
else
// only one key with no value specified in query string
nvc.Add(singlePair[0], string.Empty);
return nvc;
【讨论】:
这对windows phone 真的很有帮助,你只需要将“NameValueCollection”替换为“SortedDictionnary我需要一个比处理 OLSC 查询时已经提供的功能更通用的函数。
值可能包含多个等号 解码名称和值中的编码字符 能够在客户端框架上运行 能够在 Mobile Framework 上运行。这是我的解决方案:
Public Shared Function ParseQueryString(ByVal uri As Uri) As System.Collections.Specialized.NameValueCollection
Dim result = New System.Collections.Specialized.NameValueCollection(4)
Dim query = uri.Query
If Not String.IsNullOrEmpty(query) Then
Dim pairs = query.Substring(1).Split("&"c)
For Each pair In pairs
Dim parts = pair.Split("="c, 2)
Dim name = System.Uri.UnescapeDataString(parts(0))
Dim value = If(parts.Length = 1, String.Empty,
System.Uri.UnescapeDataString(parts(1)))
result.Add(name, value)
Next
End If
Return result
End Function
添加<Extension()>
以将功能添加到 Uri 本身可能不是一个坏主意。
【讨论】:
【参考方案6】:要在没有System.Web
的情况下执行此操作,无需自己编写,也无需额外的 NuGet 包:
-
添加对
System.Net.Http.Formatting
的引用
添加using System.Net.Http;
使用此代码:
new Uri(uri).ParseQueryString()
https://msdn.microsoft.com/en-us/library/system.net.http.uriextensions(v=vs.118).aspx
【讨论】:
你从哪里添加System.Net.Http.Formatting依赖,我相信只有添加Microsoft.AspNet.WebApi.Client NuGet包才能提供。 嗯,我的错。我猜它带有自动安装的 MVC 框架,所以我不必添加任何附加包(Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC 4\Assemblies\System.Net。 Http.Formatting.dll) System.Net.Formatting EXTENSION VS2019 是来自传统框架参考的单独列表或选项卡【参考方案7】:如果您想避免使用HttpUtility.ParseQueryString 所需的对System.Web 的依赖,您可以使用System.Net.Http
中的ParseQueryString
扩展方法ParseQueryString
。
确保在您的项目中添加对System.Net.Http
的引用(如果您还没有)。
请注意,您必须将响应正文转换为有效的Uri
,以便ParseQueryString
(在System.Net.Http
中)有效。
string body = "value1=randomvalue1&value2=randomValue2";
// "http://localhost/query?" is added to the string "body" in order to create a valid Uri.
string urlBody = "http://localhost/query?" + body;
NameValueCollection coll = new Uri(urlBody).ParseQueryString();
【讨论】:
System.Net.Formatting EXTENSION VS2019 将扩展引用与传统框架引用分开。【参考方案8】:我刚刚意识到Web API Client 有一个ParseQueryString
扩展方法,它适用于Uri
并返回一个HttpValueCollection
:
var parameters = uri.ParseQueryString();
string foo = parameters["foo"];
【讨论】:
System.Web.HttpUtility.ParseQueryString 还返回一个HttpValueCollection
(内部派生自NameValueCollection
)。两者都有相同的问题:它们不能正确解析裸键。【参考方案9】:
如果您不想要 System.Web 依赖项,只需从 HttpUtility 类中粘贴此源代码即可。
我只是从Mono 的源代码中将其组合在一起。它包含 HttpUtility 及其所有依赖项(如 IhtmlString、Helpers、HttpEncoder、HttpQSCollection)。
然后使用HttpUtility.ParseQueryString
。
https://gist.github.com/bjorn-ali-goransson/b04a7c44808bb2de8cca3fc9a3762f9c
【讨论】:
【参考方案10】: private void button1_Click( object sender, EventArgs e )
string s = @"p1=6&p2=7&p3=8";
NameValueCollection nvc = new NameValueCollection();
foreach ( string vp in Regex.Split( s, "&" ) )
string[] singlePair = Regex.Split( vp, "=" );
if ( singlePair.Length == 2 )
nvc.Add( singlePair[ 0 ], singlePair[ 1 ] );
【讨论】:
http中也允许分号作为参数分隔符,最好不要重复造*** 当车轮坏了,最好更换它。 我的一个可悲的天真反应让我想在一个洞里爬行!完美的定义:我用正则表达式解决问题,现在我有两个问题。【参考方案11】:只需访问 Request.QueryString。作为另一个答案提到的 AllKeys 只会为您提供一组键。
【讨论】:
【参考方案12】:HttpUtility.ParseQueryString(Request.Url.Query)
返回是HttpValueCollection
(内部类)。它继承自NameValueCollection
。
var qs = HttpUtility.ParseQueryString(Request.Url.Query);
qs.Remove("foo");
string url = "~/Default.aspx";
if (qs.Count > 0)
url = url + "?" + qs.ToString();
Response.Redirect(url);
【讨论】:
【参考方案13】:因为每个人似乎都在粘贴他的解决方案.. 这是我的 :-)
我需要在没有 System.Web
的类库中使用它来从存储的超链接中获取 id 参数。
我想分享一下,因为我发现这个解决方案更快更好看。
public static class Statics
public static Dictionary<string, string> QueryParse(string url)
Dictionary<string, string> qDict = new Dictionary<string, string>();
foreach (string qPair in url.Substring(url.IndexOf('?') + 1).Split('&'))
string[] qVal = qPair.Split('=');
qDict.Add(qVal[0], Uri.UnescapeDataString(qVal[1]));
return qDict;
public static string QueryGet(string url, string param)
var qDict = QueryParse(url);
return qDict[param];
用法:
Statics.QueryGet(url, "id")
【讨论】:
这种方法只有一个问题:一个查询字符串对于一个给定的参数可以有多个值。在这种情况下,您的方法将引发重复键错误。 是的,至少使用 NameValueCollection,带有重复键的查询字符串是完全合法的。 另外,您的字典区分大小写,因此 X=1 和 x=1 将是不同的键。需要新字典点击 Request.QueryString.Keys 获取所有查询字符串参数的 NameValueCollection。
【讨论】:
【参考方案15】:要获取所有 Querystring 值,请尝试以下操作:
Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring)
Dim sb As New StringBuilder("<br />")
For Each s As String In qscoll.AllKeys
Response.Write(s & " - " & qscoll(s) & "<br />")
Next s
【讨论】:
【参考方案16】: var q = Request.QueryString;
NameValueCollection qscoll = HttpUtility.ParseQueryString(q.ToString());
【讨论】:
Request
仅适用于您使用 ASP.Net。【参考方案17】:
我在 VB 中翻译成 C# 版本的 josh-brown
private System.Collections.Specialized.NameValueCollection ParseQueryString(Uri uri)
var result = new System.Collections.Specialized.NameValueCollection(4);
var query = uri.Query;
if (!String.IsNullOrEmpty(query))
var pairs = query.Substring(1).Split("&".ToCharArray());
foreach (var pair in pairs)
var parts = pair.Split("=".ToCharArray(), 2);
var name = System.Uri.UnescapeDataString(parts[0]);
var value = (parts.Length == 1) ? String.Empty : System.Uri.UnescapeDataString(parts[1]);
result.Add(name, value);
return result;
【讨论】:
【参考方案18】:let search = window.location.search;
console.log(search);
let qString = search.substring(1);
while(qString.indexOf("+") !== -1)
qString = qString.replace("+", "");
let qArray = qString.split("&");
let values = [];
for(let i = 0; i < qArray.length; i++)
let pos = qArray[i].search("=");
let keyVal = qArray[i].substring(0, pos);
let dataVal = qArray[i].substring(pos + 1);
dataVal = decodeURIComponent(dataVal);
values[keyVal] = dataVal;
【讨论】:
【参考方案19】:这是我的代码,我觉得很有用:
public String GetQueryString(string ItemToRemoveOrInsert = null, string InsertValue = null )
System.Collections.Specialized.NameValueCollection filtered = new System.Collections.Specialized.NameValueCollection(Request.QueryString);
if (ItemToRemoveOrInsert != null)
filtered.Remove(ItemToRemoveOrInsert);
if (!string.IsNullOrWhiteSpace(InsertValue))
filtered.Add(ItemToRemoveOrInsert, InsertValue);
string StrQr = string.Join("&", filtered.AllKeys.Select(key => key + "=" + filtered[key]).ToArray());
if (!string.IsNullOrWhiteSpace(StrQr))
StrQr="?" + StrQr;
return StrQr;
【讨论】:
以上是关于如何将查询字符串解析为 .NET 中的 NameValueCollection的主要内容,如果未能解决你的问题,请参考以下文章
.NET Socket.Connect 将主机名解析为 IP 地址
如何使用 ASP.NET Core 将查询字符串参数转换为看起来像目录部分?