C# 在 .NET Core 中解析和修改查询字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29992848/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Parse and modify a query string in .NET Core
提问by vcsjones
I am given an absolute URI that contains a query string. I'm looking to safely append a value to the query string, and change an existing parameter.
我得到一个包含查询字符串的绝对 URI。我希望安全地将值附加到查询字符串,并更改现有参数。
I would prefer not to tack on &foo=bar, or use regular expressions, URI escaping is tricky. Rather I want to use a built-in mechanism that I know will do this correctly and handle the escaping.
我不想添加&foo=bar或使用正则表达式,URI 转义很棘手。相反,我想使用我知道可以正确执行此操作并处理转义的内置机制。
I've foundatonof answers that all use HttpUtility. However this being ASP.NET Core, there is no more System.Web assembly anymore, thus no more HttpUtility.
我发现一个吨的答案,所有使用HttpUtility。然而,这是 ASP.NET Core,不再有 System.Web 程序集,因此不再有HttpUtility.
What is the appropriate way to do this in ASP.NET Core while targeting the core runtime?
在 ASP.NET Core 中针对核心运行时执行此操作的适当方法是什么?
采纳答案by vcsjones
If you are using ASP.NET Core 1 or 2, you can do this with Microsoft.AspNetCore.WebUtilities.QueryHelpersin the Microsoft.AspNetCore.WebUtilitiespackage.
如果您使用的是 ASP.NET Core 1 或 2,则可以Microsoft.AspNetCore.WebUtilities.QueryHelpers在Microsoft.AspNetCore.WebUtilities包中执行此操作。
If you are using ASP.NET Core 3.0 or greater, WebUtilitiesis now part of the ASP.NET SDK and does not require a separate nuget package reference.
如果您使用的是 ASP.NET Core 3.0 或更高版本,WebUtilities它现在是 ASP.NET SDK 的一部分,不需要单独的 nuget 包引用。
To parse it into a dictionary:
将其解析为字典:
var uri = new Uri(context.RedirectUri);
var queryDictionary = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query);
Note that unlike ParseQueryStringin System.Web, this returns a dictionary of type IDictionary<string, string[]>in ASP.NET Core 1.x, or IDictionary<string, StringValues>in ASP.NET Core 2.x or greater, so the value is a collection of strings. This is how the dictionary handles multiple query string parameters with the same name.
请注意,与ParseQueryStringSystem.Web不同,这将返回IDictionary<string, string[]>ASP.NET Core 1.x 或IDictionary<string, StringValues>ASP.NET Core 2.x 或更高版本中类型的字典,因此该值是字符串的集合。这就是字典处理具有相同名称的多个查询字符串参数的方式。
If you want to add a parameter on to the query string, you can use another method on QueryHelpers:
如果要向查询字符串添加参数,可以使用另一种方法 on QueryHelpers:
var parametersToAdd = new System.Collections.Generic.Dictionary<string, string> { { "resource", "foo" } };
var someUrl = "http://www.google.com";
var newUri = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString(someUrl, parametersToAdd);
Using .net core 2.2 you can get the query string using
使用 .net core 2.2,您可以使用以下方法获取查询字符串
var request = HttpContext.Request;
var query = request.query;
foreach (var item in query){
Debug.WriteLine(item)
}
You will get a collection of key:value pairs - like this
您将获得一组键:值对 - 像这样
[0] {[companyName, ]}
[1] {[shop, ]}
[2] {[breath, ]}
[3] {[hand, ]}
[4] {[eye, ]}
[5] {[firstAid, ]}
[6] {[eyeCleaner, ]}
回答by Yuval Itzchakov
HttpRequesthas a Queryproperty which exposes the parsed query string via the IReadableStringCollectioninterface:
HttpRequest有一个Query属性,它通过IReadableStringCollection接口公开解析的查询字符串:
/// <summary>
/// Gets the query value collection parsed from owin.RequestQueryString.
/// </summary>
/// <returns>The query value collection parsed from owin.RequestQueryString.</returns>
public abstract IReadableStringCollection Query { get; }
This discussionon GitHub points to it as well.
GitHub 上的这个讨论也指向了它。
回答by Ben Cull
The easiest and most intuitive way to take an absolute URI and manipulate it's query string using ASP.NET Core packages only, can be done in a few easy steps:
仅使用 ASP.NET Core 包获取绝对 URI 并操作其查询字符串的最简单、最直观的方法可以通过几个简单的步骤完成:
Install Packages
安装包
PM> Install-Package Microsoft.AspNetCore.WebUtilities
PM> Install-Package Microsoft.AspNetCore.Http.Extensions
PM> 安装包 Microsoft.AspNetCore.WebUtilities
PM> 安装包 Microsoft.AspNetCore.Http.Extensions
Important Classes
重要课程
Just to point them out, here are the two important classes we'll be using: QueryHelpers, StringValues, QueryBuilder.
只是为了指出它们,这里是我们将使用的两个重要类:QueryHelpers、StringValues、QueryBuilder。
The Code
编码
// Raw URI including query string with multiple parameters
var rawurl = "https://bencull.com/some/path?key1=val1&key2=val2&key2=valdouble&key3=";
// Parse URI, and grab everything except the query string.
var uri = new Uri(rawurl);
var baseUri = uri.GetComponents(UriComponents.Scheme | UriComponents.Host | UriComponents.Port | UriComponents.Path, UriFormat.UriEscaped);
// Grab just the query string part
var query = QueryHelpers.ParseQuery(uri.Query);
// Convert the StringValues into a list of KeyValue Pairs to make it easier to manipulate
var items = query.SelectMany(x => x.Value, (col, value) => new KeyValuePair<string, string>(col.Key, value)).ToList();
// At this point you can remove items if you want
items.RemoveAll(x => x.Key == "key3"); // Remove all values for key
items.RemoveAll(x => x.Key == "key2" && x.Value == "val2"); // Remove specific value for key
// Use the QueryBuilder to add in new items in a safe way (handles multiples and empty values)
var qb = new QueryBuilder(items);
qb.Add("nonce", "testingnonce");
qb.Add("payerId", "pyr_");
// Reconstruct the original URL with new query string
var fullUri = baseUri + qb.ToQueryString();
To keep up to date with any changes, you can check out my blog post about this here: http://benjii.me/2017/04/parse-modify-query-strings-asp-net-core/
要及时了解任何更改,您可以在此处查看我的博客文章:http: //benjii.me/2017/04/parse-modify-query-strings-asp-net-core/
回答by pimbrouwers
It's important to note that in the time since the top answer has been flagged as correct that Microsoft.AspNetCore.WebUtilitieshas had a major version update (from 1.x.x to 2.x.x).
重要的是要注意,自从最佳答案被标记为正确的时间以来,Microsoft.AspNetCore.WebUtilities已经进行了主要版本更新(从 1.xx 到 2.xx)。
That said, if you're building against netcoreapp1.1you will need to run the following, which installs the latest supported version 1.1.2:
也就是说,如果您正在构建,netcoreapp1.1则需要运行以下命令,它会安装最新的受支持版本1.1.2:
Install-Package Microsoft.AspNetCore.WebUtilities -Version 1.1.2
Install-Package Microsoft.AspNetCore.WebUtilities -Version 1.1.2
回答by Wagner Pereira
This function return Dictionary<string, string>and does not use Microsoft.xxxfor compatibility
此函数返回Dictionary<string, string>且不Microsoft.xxx用于兼容性
Accepts parameter encoding in both sides
接受双方的参数编码
Accepts duplicate keys (return last value)
接受重复键(返回最后一个值)
var rawurl = "https://emp.com/some/path?key1.name=a%20line%20with%3D&key2=val2&key2=valdouble&key3=&key%204=44#book1";
var uri = new Uri(rawurl);
Dictionary<string, string> queryString = ParseQueryString(uri.Query);
// queryString return:
// key1.name, a line with=
// key2, valdouble
// key3,
// key 4, 44
public Dictionary<string, string> ParseQueryString(string requestQueryString)
{
Dictionary<string, string> rc = new Dictionary<string, string>();
string[] ar1 = requestQueryString.Split(new char[] { '&', '?' });
foreach (string row in ar1)
{
if (string.IsNullOrEmpty(row)) continue;
int index = row.IndexOf('=');
if (index < 0) continue;
rc[Uri.UnescapeDataString(row.Substring(0, index))] = Uri.UnescapeDataString(row.Substring(index + 1)); // use Unescape only parts
}
return rc;
}
回答by Gabriel Luca
I use this as extention method, works with any number of params:
我使用它作为扩展方法,适用于任意数量的参数:
public static string AddOrReplaceQueryParameter(this HttpContext c, params string[] nameValues)
{
if (nameValues.Length%2!=0)
{
throw new Exception("nameValues: has more parameters then values or more values then parameters");
}
var qps = new Dictionary<string, StringValues>();
for (int i = 0; i < nameValues.Length; i+=2)
{
qps.Add(nameValues[i], nameValues[i + 1]);
}
return c.AddOrReplaceQueryParameters(qps);
}
public static string AddOrReplaceQueryParameters(this HttpContext c, Dictionary<string,StringValues> pvs)
{
var request = c.Request;
UriBuilder uriBuilder = new UriBuilder
{
Scheme = request.Scheme,
Host = request.Host.Host,
Port = request.Host.Port ?? 0,
Path = request.Path.ToString(),
Query = request.QueryString.ToString()
};
var queryParams = QueryHelpers.ParseQuery(uriBuilder.Query);
foreach (var (p,v) in pvs)
{
queryParams.Remove(p);
queryParams.Add(p, v);
}
uriBuilder.Query = "";
var allQPs = queryParams.ToDictionary(k => k.Key, k => k.Value.ToString());
var url = QueryHelpers.AddQueryString(uriBuilder.ToString(),allQPs);
return url;
}
Next and prev links for example in a view:
例如在视图中的下一个和上一个链接:
var next = Context.Request.HttpContext.AddOrReplaceQueryParameter("page",Model.PageIndex+1+"");
var prev = Context.Request.HttpContext.AddOrReplaceQueryParameter("page",Model.PageIndex-1+"");

