parsing并修改.NET Core中的查询string

我给了一个包含查询string的绝对URI。 我正在寻找安全地附加到查询string的值,并更改现有的参数。

我不喜欢用&foo=bar ,或者使用正则expression式,URI转义是非常棘手的。 相反,我想使用一个内置的机制,我知道会做到这一点,并处理逃跑。

我发现 了 大量的使用HttpUtility的答案。 然而,这是ASP.NET核心,再也没有更多的System.Web组件,因此没有更多的HttpUtility

针对核心运行时,在ASP.NET Core中执行此操作的适当方法是什么?

我想通过Microsoft.AspNetCore.WebUtilities包中的Microsoft.AspNetCore.WebUtilities.QueryHelpers可以做到这一点。

parsing成字典:

 var uri = new Uri(context.RedirectUri); var queryDictionary = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query); 

请注意,与System.Web中的ParseQueryString不同,这将返回一个types为IDictionary<string, string[]>的字典IDictionary<string, string[]> ,因此该值是一个string数组。 这是字典如何处理具有相同名称的多个查询string参数。

如果你想添加一个参数到查询string上,你可以在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); 

HttpRequest有一个Query属性,它通过IReadableStringCollection接口公开被parsing的查询string:

 /// <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; } 

GitHub上的这个讨论也指出了这一点。

使用ASP.NET Core软件包获取绝对URI并操作查询string的最简单和最直观的方法可以通过几个简单的步骤完成:

安装软件包

PM> Install-Package Microsoft.AspNetCore.WebUtilities
PM> Install-Package Microsoft.AspNetCore.Http.Extensions

重要的类

只是为了指出,这里是我们将使用的两个重要的类: QueryHelpers , StringValues , QueryBuilder 。

代码

 // 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(); 

要跟上任何变化,你可以看看我的博客文章关于这个: http : //benjii.me/2017/04/parse-modify-query-strings-asp-net-core/

重要的是要注意,从顶级答案被标记为正确的那一刻起, Microsoft.AspNetCore.WebUtilities已经进行了主版本更新(从1.xx到2.xx)。

也就是说,如果您是针对netcoreapp1.1构build的,则需要运行以下命令,它将安装最新的受支持版本1.1.2

Install-Package Microsoft.AspNetCore.WebUtilities -Version 1.1.2

此函数返回Dictionary<string, string> ,并不使用Microsoft.xxx兼容性

接受双方的参数编码

接受重复的键(返回最后一个值)

 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('='); rc[Uri.UnescapeDataString(row.Substring(0, index))] = Uri.UnescapeDataString(row.Substring(index + 1)); // use Unescape only parts } return rc; }