如何通过密钥从Url中有效删除查询字符串?

The*_*ght 33 .net c# regex url query-string

如何从Url中删除Key的查询字符串?

我有以下方法工作正常但只是想知道有更好/更短的方式?或内置的.NET方法,可以更有效地做到这一点?

 public static string RemoveQueryStringByKey(string url, string key)
        {
            var indexOfQuestionMark = url.IndexOf("?");
            if (indexOfQuestionMark == -1)
            {
                return url;
            }

            var result = url.Substring(0, indexOfQuestionMark);
            var queryStrings = url.Substring(indexOfQuestionMark + 1);
            var queryStringParts = queryStrings.Split(new [] {'&'});
            var isFirstAdded = false;

            for (int index = 0; index <queryStringParts.Length; index++)
            {
                var keyValue = queryStringParts[index].Split(new char[] { '=' });
                if (keyValue[0] == key)
                {
                    continue;
                }

                if (!isFirstAdded)
                {
                    result += "?";
                    isFirstAdded = true;
                }
                else
                {
                    result += "&";
                }

                result += queryStringParts[index];
            }

            return result;
        }
Run Code Online (Sandbox Code Playgroud)

例如,我可以称之为:

  Console.WriteLine(RemoveQueryStringByKey(@"http://www.domain.com/uk_pa/PostDetail.aspx?hello=hi&xpid=4578", "xpid"));
Run Code Online (Sandbox Code Playgroud)

希望问题很清楚.

谢谢,

The*_*ght 85

这很好用:

public static string RemoveQueryStringByKey(string url, string key)
{                   
    var uri = new Uri(url);

    // this gets all the query string key value pairs as a collection
    var newQueryString = HttpUtility.ParseQueryString(uri.Query);

    // this removes the key if exists
    newQueryString.Remove(key);

    // this gets the page path from root without QueryString
    string pagePathWithoutQueryString = uri.GetLeftPart(UriPartial.Path);

    return newQueryString.Count > 0
        ? String.Format("{0}?{1}", pagePathWithoutQueryString, newQueryString)
        : pagePathWithoutQueryString;
}
Run Code Online (Sandbox Code Playgroud)

一个例子:

RemoveQueryStringByKey("https://www.google.co.uk/search?#hl=en&output=search&sclient=psy-ab&q=cookie", "q");
Run Code Online (Sandbox Code Playgroud)

并返回:

https://www.google.co.uk/search?#hl=en&output=search&sclient=psy-ab
Run Code Online (Sandbox Code Playgroud)

  • string不包含FormatWith方法的定义 (2认同)
  • 这个答案错过了 Uri.Fragment (哈希#xxx)处理。因此像“https://www.google.co.uk/search?#hl=en&amp;output=search&amp;sclient=psy-ab&amp;q=cookie#xxx”这样的URL在处理后会丢失“#xxx”。所以返回值要加上uri.Fragment (2认同)

C.M*_*.M. 11

    var queryString = "hello=hi&xpid=4578";
    var qs = System.Web.HttpUtility.ParseQueryString(queryString);
    qs.Remove("xpid");
    var newQuerystring = qs.ToString();
Run Code Online (Sandbox Code Playgroud)

这在 .NET 5 中仍然有效。


小智 8

我知道这是一个相当老的问题,但我读到的所有内容都感觉有点复杂。

public Uri GetUriWithoutQueryParam( Uri originalUri, string paramKey ) {
  NameValueCollection newQuery = HttpUtility.ParseQueryString( originalUri.Query );
  newQuery.Remove( paramKey );
  return new UriBuilder( originalUri ) { Query = newQuery.ToString() }.Uri;
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*ger 5

System 命名空间中有一个名为UriBuilder的有用类。我们可以将它与几个扩展方法一起使用来执行以下操作:

Uri u = new Uri("http://example.com?key1=value1&key2=value2");
u = u.DropQueryItem("key1");
Run Code Online (Sandbox Code Playgroud)

或者像这样:

Uri u = new Uri("http://example.com?key1=value1&key2=value2");
UriBuilder b = new UriBuilder(u);
b.RemoveQueryItem("key1");
u = b.Uri;
Run Code Online (Sandbox Code Playgroud)

扩展方法:

using System;
using System.Collections.Specialized;
using System.Text;
using System.Text.RegularExpressions;

public static class UriExtensions
{
    public static Uri DropQueryItem(this Uri u, string key)
    {
        UriBuilder b = new UriBuilder(u);
        b.RemoveQueryItem(key);
        return b.Uri;
    }
}
public static class UriBuilderExtensions
{
    private static string _ParseQueryPattern = @"(?<key>[^&=]+)={0,1}(?<value>[^&]*)";
    private static Regex _ParseQueryRegex = null;

    private static Regex ParseQueryRegex
    {
        get
        {
            if (_ParseQueryRegex == null)
            {
                _ParseQueryRegex = new Regex(_ParseQueryPattern, RegexOptions.Compiled | RegexOptions.Singleline);
            }
            return _ParseQueryRegex;

        }
    }

    public static void SetQueryItem(this UriBuilder b, string key, string value)
    {
        NameValueCollection parms = ParseQueryString(b.Query);
        parms[key] = value;
        b.Query = RenderQuery(parms);
    }

    public static void RemoveQueryItem(this UriBuilder b, string key)
    {
        NameValueCollection parms = ParseQueryString(b.Query);
        parms.Remove(key);
        b.Query = RenderQuery(parms);
    }       
    private static string RenderQuery(NameValueCollection parms)
    {
        StringBuilder sb = new StringBuilder();
        for (int i=0; i<parms.Count; i++)
        {
            string key = parms.Keys[i];
            sb.Append(key + "=" + parms[key]);
            if (i < parms.Count - 1)
            {
                sb.Append("&");
            }
        }
        return sb.ToString();
    }
    public static NameValueCollection ParseQueryString(string query, bool caseSensitive = true)
    {
        NameValueCollection pairs = new NameValueCollection(caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase);

        string q = query.Trim().TrimStart(new char[] {'?'});
        MatchCollection matches = ParseQueryRegex.Matches(q);

        foreach (Match m in matches)
        {
            string key = m.Groups["key"].Value;
            string value = m.Groups["value"].Value;
            if (pairs[key] != null)
            {
                pairs[key] = pairs[key] + "," + value;
            }
            else
            {
                pairs[key] = value;
            }

        }

        return pairs;

    }

}
Run Code Online (Sandbox Code Playgroud)

  • @TommyHolman 对此表示抱歉。事实证明,RemoveQueryItem 是我自己在 UriBuilder 上的扩展方法。我已经更新了我的答案以包含它。 (2认同)