web-dev-qa-db-fra.com

Comment supprimer efficacement une chaîne de requête par clé d'une url?

Comment supprimer une chaîne de requête par clé d'une url?

J'ai la méthode ci-dessous qui fonctionne bien, mais je me demandais simplement s'il y avait un moyen meilleur/plus court ou une méthode .NET intégrée qui peut le faire plus efficacement?

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

Par exemple, je peux l'appeler comme suit:

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

J'espère que la question est claire.

Merci,

29
The Light

Cela fonctionne bien:

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

un exemple:

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

et retourne:

https://www.google.co.uk/#hl=en&output=search&sclient=psy-ab
76
The Light

Nous pouvons aussi le faire en utilisant regex 

string queryString = "Default.aspx?Agent=10&Language=2"; //Request.QueryString.ToString();
string parameterToRemove="Language";   //parameter which we want to remove
string regex=string.Format("(&{0}=[^&\s]+|(?<=\?){0}=[^&\s]+&?)",parameterToRemove);   //this will not work for javascript, for javascript you can do following
string finalQS = Regex.Replace(queryString, regex, "");

//javascript(following is not js syntex, just want to give idea how we can able do it in js)
string regex1 = string.Format("(&{0}=[^&\s]+)",parameterToRemove);
string regex2 = string.Format("(\?{0}=[^&\s]+&?)",parameterToRemove);
string finalQS = Regex.Replace(queryString, regex1, "").Replace(queryString, regex2, "");

https://regexr.com/3i9vj

2
yajiv
var qs = System.Web.HttpUtility.ParseQueryString(queryString);
var str = qs.Get(key);

Cette classe d'assistance a également des méthodes Set.

1
C.M.

Que dis-tu de ça:

        string RemoveQueryStringByKey(string url, string key)
    {
        string ret = string.Empty;

        int index = url.IndexOf(key);
        if (index > -1)
        {
            string post = string.Empty;

            // Find end of key's value
            int endIndex = url.IndexOf('&', index);
            if (endIndex != -1) // Last query string value?
            {
                post = url.Substring(endIndex, url.Length - endIndex);
            }

            // Decrement for ? or & character
            --index;
            ret = url.Substring(0, index) + post;
        }

        return ret;
    }
1
NickV

J'ai trouvé un moyen sans utiliser Regex:

private string RemoveQueryStringByKey(string sURL, string sKey) {
    string sOutput = string.Empty;

    int iQuestion = sURL.IndexOf('?');
    if (iQuestion == -1) return (sURL);

    int iKey = sURL.Substring(iQuestion).IndexOf(sKey) + iQuestion;
    if (iKey == -1) return (sURL);

    int iNextAnd = sURL.Substring(iKey).IndexOf('&') + iKey + 1;

    if (iNextAnd == -1) {
        sOutput = sURL.Substring(0, iKey - 1);
    }
    else {
        sOutput = sURL.Remove(iKey, iNextAnd - iKey);
    }

    return (sOutput);
}

J'ai essayé cela en ajoutant un autre champ à la fin, et cela fonctionne bien pour cela aussi.

1
krillgar

Il existe une classe utile appelée UriBuilder dans l'espace de noms System. Nous pouvons l’utiliser avec quelques méthodes d’extension pour effectuer les opérations suivantes:

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

Ou comme ceci:

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

Les méthodes d'extension:

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;

    }

}
1

Voici une solution complète qui fonctionne avec> = 0 paramètres spécifiés, et toute forme d’URL:

    /// <summary>
    /// Given a URL in any format, return URL with specified query string param removed if it exists
    /// </summary>
    public static string StripQueryStringParam(string url, string paramToRemove)
    {
        return StripQueryStringParams(url, new List<string> {paramToRemove});
    }

    /// <summary>
    /// Given a URL in any format, return URL with specified query string params removed if it exists
    /// </summary>
    public static string StripQueryStringParams(string url, List<string> paramsToRemove)
    {
        if (paramsToRemove == null || !paramsToRemove.Any()) return url;

        var splitUrl = url.Split('?');
        if (splitUrl.Length == 1) return url;

        var urlFirstPart = splitUrl[0];
        var urlSecondPart = splitUrl[1];

        // Even though in most cases # isn't available to context,
        // we may be passing it in explicitly for helper urls
        var secondPartSplit = urlSecondPart.Split('#');
        var querystring = secondPartSplit[0];
        var hashUrlPart = string.Empty;
        if (secondPartSplit.Length > 1)
        {
            hashUrlPart = "#" + secondPartSplit[1];
        }
        var nvc = HttpUtility.ParseQueryString(querystring);
        if (!nvc.HasKeys()) return url;

        // Remove any matches
        foreach (var key in nvc.AllKeys)
        {
            if (paramsToRemove.Contains(key))
            {
                nvc.Remove(key);
            }
        }

        if (!nvc.HasKeys()) return urlFirstPart;
        return urlFirstPart + 
               "?" + string.Join("&", nvc.AllKeys.Select(c => c.ToString() + "=" + nvc[c.ToString()])) + 
               hashUrlPart;
    }
0
Tom Gullen

Code ci-dessous avant de supprimer votre QueryString

 PropertyInfo isreadonly = 
          typeof(System.Collections.Specialized.NameValueCollection).GetProperty(
          "IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
        // make collection editable
        isreadonly.SetValue(this.Request.QueryString, false, null);
        // remove
        this.Request.QueryString.Remove("yourKey");
0

Désolé, c'est un peu sale, mais cela devrait fonctionner dans un cadre plus ancien. 

public String RemoveQueryString( String rawUrl  , String keyName)
{
    var currentURL_Split =  rawUrl.Split('&').ToList();
    currentURL_Split = currentURL_Split.Where(o => !o.ToLower().StartsWith(keyName.ToLower()+"=")).ToList();
    String New_RemovedKey = String.Join("&", currentURL_Split.ToArray()); 
    New_RemovedKey = New_RemovedKey.Replace("&&", "&");
    return New_RemovedKey;
}
0
Kanit P.
public static string RemoveQueryStringByKey(string sURL, string sKey)
    {
        string sOutput = string.Empty;
        string sToReplace = string.Empty;

        int iFindTheKey = sURL.IndexOf(sKey);
        if (iFindTheKey == -1) return (sURL);

        int iQuestion = sURL.IndexOf('?');
        if (iQuestion == -1) return (sURL);

        string sEverythingBehindQ = sURL.Substring(iQuestion);
        List<string> everythingBehindQ = new List<string>(sEverythingBehindQ.Split('&'));
        foreach (string OneParamPair in everythingBehindQ)
        {
            int iIsKeyInThisParamPair = OneParamPair.IndexOf(sKey);
            if (iIsKeyInThisParamPair != -1)
            {
                sToReplace = "&" + OneParamPair;
            }
        }

        sOutput = sURL.Replace(sToReplace, "");
        return (sOutput);
    }
0
Ash

Voici ma solution: 

J'ai ajouté une validation d'entrée supplémentaire. 

public static void TryRemoveQueryStringByKey(ref string url, string key)
{
    if (string.IsNullOrEmpty(url) ||
        string.IsNullOrEmpty(key) ||
        Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute) == false)
    {
        return false;
    }            

    try
    {
        Uri uri = new Uri(url);

        // This gets all the query string key value pairs as a collection
        NameValueCollection queryCollection = HttpUtility.ParseQueryString(uri.Query);
        string keyValue = queryCollection.Get(key);

        if (url.IndexOf("&" + key + "=" + keyValue, StringComparison.OrdinalIgnoreCase) >= 0)
        {
            url = url.Replace("&" + key + "=" + keyValue, String.Empty);
            return true;
        }
        else if (url.IndexOf("?" + key + "=" + keyValue, StringComparison.OrdinalIgnoreCase) >= 0)
        {
            url = url.Replace("?" + key + "=" + keyValue, String.Empty);
            return true;
        }
        else
        {
            return false;
        }
    }
    catch
    {
        return false;
    }
}

Quelques exemples de tests unitaires:

string url1 = "http://www.gmail.com?a=1&cookie=cookieValue"
Assert.IsTrue(TryRemoveQueryStringByKey(ref url1,"cookie")); //OUTPUT: "http://www.gmail.com?a=1"

string url2 = "http://www.gmail.com?cookie=cookieValue"  
Assert.IsTrue(TryRemoveQueryStringByKey(ref url2,"cookie")); //OUTPUT: "http://www.gmail.com"

string url3 = "http://www.gmail.com?cookie="  
Assert.IsTrue(TryRemoveQueryStringByKey(ref url2,"cookie")); //OUTPUT: "http://www.gmail.com"
0
Shahar Shokrani

Je pense que le moyen le plus court (que je crois produit une URL valide dans tous les cas, en supposant que l'URL soit valide pour commencer) serait d'utiliser cette expression rationnelle (où getRidOf est le nom de la variable que vous essayez d'utiliser. supprimer) et le remplacement est une chaîne de longueur nulle ""):

(?<=[?&])getRidOf=[^&]*(&|$)

ou peut-être même 

\bgetRidOf=[^&]*(&|$)

bien que les URL les plus jolies _ absolues ne soient peut-être pas absolues, je pense elles sont toutes valides:

         INPUT                                         OUTPUT
      -----------                                   ------------
blah.com/blah.php?getRidOf=d.co&blah=foo        blah.com/blah.php?blah=foo
blah.com/blah.php?f=0&getRidOf=d.co&blah=foo    blah.com/blah.php?f=0&blah=foo
blah.com/blah.php?hello=true&getRidOf=d.co      blah.com/blah.php?hello=true&
blah.com/blah.php?getRidOf=d.co                 blah.com/blah.php?

et c'est un regex simple remplacer:

Dim RegexObj as Regex = New Regex("(?<=[?&])getRidOf=[^&]*(&|$)")
RegexObj.Replace("source.url.com/find.htm?replace=true&getRidOf=PLEASE!!!", "")

... devrait aboutir à la chaîne:

"source.url.com/find.htm?replace=true&"

... qui semble être valable pour une application ASP.Net, alors que replace est égal à true (pas true& ou quoi que ce soit de ce genre)

Je vais essayer de l'adapter si vous avez un cas où cela ne fonctionnera pas :)

0
Code Jockey