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

时间:2015-05-01 18:31:55

标签: c# asp.net asp.net-core

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

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

found a ton个答案都使用HttpUtility。然而,这是ASP.NET Core,不再有System.Web程序集,因此不再有HttpUtility

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

6 个答案:

答案 0 :(得分:116)

如果您使用的是ASP.NET Core 1或2,则可以使用Microsoft.AspNetCore.WebUtilities包中的Uncaught TypeError: Cannot read property 'setup' of undefined 执行此操作。

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

将其解析为字典:

WebUtilities

请注意,与System.Web中的var uri = new Uri(context.RedirectUri); var queryDictionary = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query); 不同,它会在ASP.NET Core 1.x中返回类型为ParseQueryString的字典,或在ASP.NET Core 2.x中返回IDictionary<string, string[]>或者更大,因此值是字符串的集合。这就是字典处理多个具有相同名称的查询字符串参数的方式。

如果要在查询字符串上添加参数,可以在IDictionary<string, StringValues>上使用其他方法:

QueryHelpers

答案 1 :(得分:24)

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

安装包

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

重要课程

只是指出它们,以下是我们将要使用的两个重要类:QueryHelpersStringValuesQueryBuilder

守则

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

答案 2 :(得分:16)

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; }
GitHub上的

This discussion也指向它。

答案 3 :(得分:8)

此函数返回import UIKit class ViewController: UIViewController { // I will need to use these later @IBOutlet weak var SubmitB: UIButton! @IBOutlet weak var DateB: UIDatePicker! @IBOutlet weak var ResetB: UIButton! @IBOutlet weak var LotI: UITextField! @IBOutlet weak var BlockI: UITextField! @IBOutlet weak var EmailI: UITextField! @IBOutlet weak var BuilderI: UITextField! @IBOutlet weak var SubdivisionI: UITextField! @IBOutlet weak var FilingI: UITextField! @IBOutlet weak var AddressI: UITextField! @IBOutlet weak var HSSPPP: UISwitch! @IBOutlet weak var HSUTSLNC: UISwitch! @IBOutlet weak var HSOSC: UISwitch! @IBOutlet weak var FFCPPPP: UISwitch! @IBOutlet weak var FFCFSC: UISwitch! @IBOutlet weak var FFCOSC: UISwitch! @IBOutlet weak var RGSSPPP: UISwitch! @IBOutlet weak var RGSOSC: UISwitch! @IBOutlet weak var ISSSFR: UISwitch! @IBOutlet weak var ISFNC: UISwitch! @IBOutlet weak var ISOSC: UISwitch! @IBOutlet weak var GSPSSFG: UISwitch! @IBOutlet weak var GSFGF: UISwitch! @IBOutlet weak var GSFDNMC: UISwitch! @IBOutlet weak var GSOSC: UISwitch! @IBOutlet weak var CommentsI: UITextView! @IBAction func ResetBA(_ sender: Any) { //this is where I am stuck } } 并且不使用Dictionary<string, string>进行兼容性

接受双方的参数编码

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

Microsoft.xxx

答案 4 :(得分:1)

重要的是要注意,自从最高答案被标记为正确以来,Microsoft.AspNetCore.WebUtilities已经进行了主要版本更新(从1.x.x到2.x.x)。

也就是说,如果您是针对netcoreapp1.1构建的,则需要运行以下内容,然后安装最新支持的版本1.1.2

Install-Package Microsoft.AspNetCore.WebUtilities -Version 1.1.2

答案 5 :(得分:1)

我将其用作扩展方法,可用于任何数量的参数:

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

例如视图中的下一个和上一个链接:

var next = Context.Request.HttpContext.AddOrReplaceQueryParameter("page",Model.PageIndex+1+"");

var prev = Context.Request.HttpContext.AddOrReplaceQueryParameter("page",Model.PageIndex-1+"");