我想将类似于 p1=6&p2=7&p3=8
的字符串解析为 NameValueCollection
。
当你无法访问 Page.Request
对象时,最优雅的方法是什么?
我想将类似于 p1=6&p2=7&p3=8
的字符串解析为 NameValueCollection
。
当你无法访问 Page.Request
对象时,最优雅的方法是什么?
这个有内置的.NET工具来完成:HttpUtility.ParseQueryString
// C#
NameValueCollection qscoll = HttpUtility.ParseQueryString(querystring);
' VB.NET
Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring)
您可能需要用new Uri(fullUrl).Query
替换querystring
。
HttpUtility.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);
}
}
?foo=1&bar
。HttpUtility
将解析为 { key = null, value = "bar" }
。 - Thomas Levesquevar uri = new Uri("https://dev59.com/5HVD5IYBdhLWcg3wKYL-#22167748?p1=6&p2=7&p3=8");
NameValueCollection query = uri.ParseQueryString();
我想要去除对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;
}
如果不使用System.Web
,也不想自己编写代码或添加额外的NuGet包,可以按以下步骤操作:
System.Net.Http.Formatting
using System.Net.Http;
Use this code:
new Uri(uri).ParseQueryString()
https://msdn.microsoft.com/en-us/library/system.net.http.uriextensions(v=vs.118).aspx
我需要一个比现有 OLSC 查询提供的功能更加灵活的函数。
这是我的解决方案:
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 本身添加这种功能。
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();
我从Mono的源代码中编写了这个,它包含了HttpUtility和所有依赖项(如IHtmlString、Helpers、HttpEncoder、HttpQSCollection)。
然后使用HttpUtility.ParseQueryString
。
https://gist.github.com/bjorn-ali-goransson/b04a7c44808bb2de8cca3fc9a3762f9c
我刚刚意识到,Web API Client有一个ParseQueryString
扩展方法,可以在Uri
上工作,并返回一个HttpValueCollection
:
var parameters = uri.ParseQueryString();
string foo = parameters["foo"];
HttpValueCollection
(它在内部派生自 NameValueCollection
)。两者都有同样的问题:它们无法正确解析裸键。 - Suncat2000 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 ] );
}
}
}
HttpUtility.ParseQueryString
是我的建议,但在HttpUtility.ParseQueryString("&X=1&X=2&X=3")
的情况下,结果会变成....X=1,2,3...
。虽然同名参数出现多次并不常见,但需要支持控制器参数,例如int[], IEnumerable<int>等(此类参数可能用于支持多个复选框),请参见MS网站中的“相同查询字符串变量的多个实例合并为一个条目”。手工编写该方法可能是您唯一的选择。 - dunxz