webentwicklung-frage-antwort-db.com.de

Wie kann man eine Abfragezeichenfolge effizient mit einem Schlüssel aus einer URL entfernen?

So entfernen Sie eine Abfragezeichenfolge mit einem Schlüssel aus einer URL

Ich habe die folgende Methode, die gut funktioniert, aber ich frage mich, ob es einen besseren/kürzeren Weg gibt? oder eine eingebaute .NET-Methode, die dies effizienter erledigen kann?

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

Ich kann es zum Beispiel so nennen:

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

Hoffe die Frage ist klar.

Vielen Dank,

29
The Light

Das funktioniert gut:

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

ein Beispiel:

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

und kehrt zurück:

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

Wir können es auch mit Regex tun 

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

Diese Hilfsklasse hat auch Set-Methoden.

1
C.M.

Wie wäre es damit:

        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

Ich habe einen Weg gefunden, ohne Regex zu benutzen:

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

Ich habe es mit einem weiteren Feld am Ende ausprobiert, und das funktioniert auch gut.

1
krillgar

Es gibt eine nützliche Klasse namens UriBuilder im Namespace System. Wir können es zusammen mit ein paar Erweiterungsmethoden verwenden, um Folgendes zu tun:

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

Oder so:

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

Die Erweiterungsmethoden:

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;

    }

}

Hier ist eine vollständige Lösung, die mit angegebenen Parametern von> = 0 und jeder Form von URL funktioniert:

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

Nachfolgender Code vor dem Löschen Ihrer 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

Sorry, das ist ein bisschen schmutzig, sollte aber in älteren Frameworks funktionieren 

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

Hier ist meine Lösung: 

Ich habe ein paar zusätzliche Eingabevalidierungen hinzugefügt. 

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

Einige Unit-Test-Beispiele:

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

Ich denke, der kürzeste Weg (den ich glaube in allen Fällen eine gültige URL herstellt, vorausgesetzt, die URL war anfangs gültig) wäre die Verwendung dieses Regex (wobei getRidOf der Variablenname ist, den Sie entfernen möchten ) und die Ersetzung ist eine Zeichenfolge der Länge Null (""):

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

oder vielleicht sogar 

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

möglicherweise nicht die absoluten schönsten URLs, ich denke sie sind alle gültig:

         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?

und es ist eine einfache Regex ersetzen:

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

... sollte den String ergeben:

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

... was für eine ASP.Net-Anwendung gültig zu sein scheint, während replace gleich true ist (nicht true& oder ähnliches)

Ich werde versuchen, es anzupassen, wenn Sie einen Fall haben, in dem es nicht funktioniert :)

0
Code Jockey