解析并修改.NET Core中的查询字符串

vcs*_*nes 97 c# asp.net asp.net-core

我得到一个包含查询字符串的绝对URI.我希望安全地将值附加到查询字符串,并更改现有参数.

我不想&foo=bar使用或使用正则表达式,URI转义是棘手的.相反,我想使用内置机制,我知道这将正确地执行此操作并处理转义.

发现 大量的答案都可以使用HttpUtility.然而,这是ASP.NET Core,不再有System.Web程序集,因此不再需要HttpUtility.

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

vcs*_*nes 130

如果您使用的是ASP.NET Core 1或2,则可以Microsoft.AspNetCore.WebUtilities.QueryHelpersMicrosoft.AspNetCore.WebUtilities包中执行此操作.

如果您使用的是ASP.NET Core 3.0或更高版本,WebUtilities则它现在是ASP.NET SDK的一部分,并且不需要单独的nuget包引用.

要将其解析为字典:

var uri = new Uri(context.RedirectUri);
var queryDictionary = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query);
Run Code Online (Sandbox Code Playgroud)

请注意,与ParseQueryStringSystem.Web 不同,它返回IDictionary<string, string[]>ASP.NET Core 1.x或IDictionary<string, StringValues>ASP.NET Core 2.x或更高版本中的类型字典,因此该值是字符串的集合.这是字典处理具有相同名称的多个查询字符串参数的方式.

如果要在查询字符串上添加参数,可以使用另一种方法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);
Run Code Online (Sandbox Code Playgroud)

  • @Jaime很棒的观察!您能否使用该更新编辑我的答案,以便您获得荣誉? (6认同)
  • 完成版.保留传统.net版本的旧命名空间. (3认同)
  • 在 Asp.net Core 2.2 中,这不起作用。ParseQuery 返回一个 Dictionary&lt;string, StringValues&gt; 并且没有接受它的 AddQueryString 。 (3认同)
  • 现在的返回类型为IDictionary &lt;string,StringValues&gt;,而不是IDictionary &lt;string,string []&gt; (2认同)

Ben*_*ull 30

使用ASP.NET Core包获取绝对URI并操纵它的查询字符串的最简单,最直观的方法可以通过几个简单的步骤完成:

安装包

PM>安装包Microsoft.AspNetCore.WebUtilities
PM>安装包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();
Run Code Online (Sandbox Code Playgroud)

要及时了解任何更改,您可以在此处查看我的博客文章:http://benjii.me/2017/04/parse-modify-query-strings-asp-net-core/


Yuv*_*kov 17

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; }
Run Code Online (Sandbox Code Playgroud)

关于GitHub的讨论也指向了它.


Wag*_*ira 9

此函数返回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('=');
        if (index < 0) continue;
        rc[Uri.UnescapeDataString(row.Substring(0, index))] = Uri.UnescapeDataString(row.Substring(index + 1)); // use Unescape only parts          
     }
     return rc;
}
Run Code Online (Sandbox Code Playgroud)