Заменить элемент в строке запроса - PullRequest
14 голосов
/ 21 апреля 2009

У меня есть URL, который также может содержать часть строки запроса, строка запроса может быть пустой или содержать несколько элементов.

Я хочу заменить один из элементов в строке запроса или добавить его, если элемент еще не существует.

У меня есть объект URI с полным URL.

Моей первой идеей было использовать регулярные выражения и некоторую магию строк, которая должна была это сделать.

Но это кажется немного шатким, возможно, у фреймворка есть какой-то класс построителя строки запроса?

Ответы [ 11 ]

42 голосов
/ 02 мая 2012

Я нашел, что это было более элегантное решение

var qs = HttpUtility.ParseQueryString(Request.QueryString.ToString());
qs.Set("item", newItemValue);
Console.WriteLine(qs.ToString());
17 голосов
/ 15 октября 2014

Позволяет иметь этот URL: https://localhost/video?param1=value1

При первом обновлении конкретного параметра строки запроса новое значение:

var uri = new Uri("https://localhost/video?param1=value1");
var qs = HttpUtility.ParseQueryString(uri.Query);
qs.Set("param1", "newValue2");

Далее создайте UriBuilder и обновите свойство Query, чтобы получить новый URI с измененным значением параметра.

var uriBuilder = new UriBuilder(uri);
uriBuilder.Query = qs.ToString();
var newUri = uriBuilder.Uri;

Теперь у вас есть в newUri это значение: https://localhost/video?param1=newValue2

4 голосов
/ 08 февраля 2012

Я использую следующий метод:

    public static string replaceQueryString(System.Web.HttpRequest request, string key, string value)
    {
        System.Collections.Specialized.NameValueCollection t = HttpUtility.ParseQueryString(request.Url.Query);
        t.Set(key, value);
        return t.ToString();
    }
4 голосов
/ 05 октября 2010
string link = page.Request.Url.ToString();

if(page.Request.Url.Query == "")
    link  += "?pageIndex=" + pageIndex;
else if (page.Request.QueryString["pageIndex"] != "")
{
    var idx = page.Request.QueryString["pageIndex"];
    link = link.Replace("pageIndex=" + idx, "pageIndex=" + pageIndex);
}
else 
    link += "&pageIndex=" + pageIndex;

Кажется, это работает очень хорошо.

3 голосов
/ 21 апреля 2009

Может быть, вы могли бы использовать класс <a href="http://msdn.microsoft.com/en-us/library/system.uribuilder.aspx" rel="nofollow noreferrer">System.UriBuilder</a>. Имеет свойство <a href="http://msdn.microsoft.com/en-us/library/system.uribuilder.query.aspx" rel="nofollow noreferrer">Query</a>.

3 голосов
/ 21 апреля 2009

Нет, в каркасе нет существующего класса QueryStringBuilder, но обычно информация строки запроса в HTTP-запросе доступна в виде итерируемого и доступного для поиска NameValueCollection через свойство Request.Querystring.

Поскольку вы начинаете с объекта Uri, вам необходимо получить часть строки запроса, используя свойство Query объекта Uri. Это даст строку вида:

Uri myURI = new Uri("http://www.mywebsite.com/page.aspx?Val1=A&Val2=B&Val3=C");
string querystring = myURI.Query;

// Outputs: "?Val1=A&Val2=B&Val3=C". Note the ? prefix!
Console.WriteLine(querystring);

Затем вы можете разбить эту строку на символ амперсанда, чтобы дифференцировать ее на разные пары параметров-значений строки запроса. Затем снова разделите каждый параметр символа «=», чтобы разделить его на ключ и значение.

Поскольку вашей конечной целью является поиск определенного ключа строки запроса и, если необходимо, его создание, вам следует попытаться (пере) создать коллекцию (предпочтительно общую), которая позволяет легко выполнять поиск в коллекции, аналогично объект, предоставленный NameValueCollection класс.

2 голосов
/ 14 октября 2011

Я использовал следующий код для добавления / замены значения параметра в URL текущего запроса:

    public static string CurrentUrlWithParam(this UrlHelper helper, string paramName, string paramValue)
    {
        var url = helper.RequestContext.HttpContext.Request.Url;
        var sb = new StringBuilder();

        sb.AppendFormat("{0}://{1}{2}{3}",
                        url.Scheme,
                        url.Host,
                        url.IsDefaultPort ? "" : ":" + url.Port,
                        url.LocalPath);

        var isFirst = true;

        if (!String.IsNullOrWhiteSpace(url.Query))
        {
            var queryStrings = url.Query.Split(new[] { '?', ';' });
            foreach (var queryString in queryStrings)
            {
                if (!String.IsNullOrWhiteSpace(queryString) && !queryString.StartsWith(paramName + "="))
                {
                    sb.AppendFormat("{0}{1}", isFirst ? "?" : ";", queryString);
                    isFirst = false;
                }
            }
        }

        sb.AppendFormat("{0}{1}={2}", isFirst ? "?" : ";", paramName, paramValue);

        return sb.ToString();
    }

Может быть, это поможет другим при поиске этой темы.

Обновление:

Только что увидел подсказку об UriBuilder и сделал вторую версию, используя UriBuilder, StringBuilder и Linq:

    public static string CurrentUrlWithParam(this UrlHelper helper, string paramName, string paramValue)
    {
        var url = helper.RequestContext.HttpContext.Request.Url;
        var ub = new UriBuilder(url.Scheme, url.Host, url.Port, url.LocalPath);

        // Query string
        var sb = new StringBuilder();
        var isFirst = true;
        if (!String.IsNullOrWhiteSpace(url.Query))
        {
            var queryStrings = url.Query.Split(new[] { '?', ';' });
            foreach (var queryString in queryStrings.Where(queryString => !String.IsNullOrWhiteSpace(queryString) && !queryString.StartsWith(paramName + "=")))
            {
                sb.AppendFormat("{0}{1}", isFirst ? "" : ";", queryString);
                isFirst = false;
            }
        }
        sb.AppendFormat("{0}{1}={2}", isFirst ? "" : ";", paramName, paramValue);
        ub.Query = sb.ToString();

        return ub.ToString();
    }
1 голос
/ 21 апреля 2009

Я согласен с Церебром. Придерживаясь принципа KISS, у вас есть строка запроса,

string querystring = myURI.Query; 

Вы знаете, что ищете и чем хотите заменить.

Так что используйте что-то вроде этого: -

if (querystring == "") 
  myURI.Query += "?" + replacestring; 
else 
  querystring.replace (searchstring, replacestring); // not too sure of syntax !!
0 голосов
/ 17 ноября 2015
   public class QueryParams : Dictionary<string,string>
   {
       private Uri originolUrl;
       private Uri ammendedUrl;
       private string schemeName;
       private string hostname;
       private string path;

       public QueryParams(Uri url)
       {
           this.originolUrl = url;
           schemeName = url.Scheme;
           hostname = url.Host;
           path = url.AbsolutePath;
           //check uri to see if it has a query
           if (url.Query.Count() > 1)
           {
               //we grab the query and strip of the question mark as we do not want it attached
               string query = url.Query.TrimStart("?".ToArray());
               //we grab each query and place them into an array
               string[] parms = query.Split("&".ToArray());
               foreach (string str in parms)
               {
                   // we split each query into two strings(key) and (value) and place into array
                   string[] param = str.Split("=".ToArray());
                   //we add the strings to this dictionary
                   this.Add(param[0], param[1]);
               }
           }
       }


       public QueryParams Set(string paramName, string value)
       {

           if(this.ContainsKey(paramName))
           {
               //if key exists change value
               this[paramName] = value;
               return (this);
           }
           else
           {
               this.Add(paramName, value);
               return this;
           }
       }
       public QueryParams Set(string paramName, int value)
       {
           if (this.ContainsKey(paramName))
           {
               //if key exists change value
               this[paramName] = value.ToString();
               return (this);
           }
           else 
           {
               this.Add(paramName, value);
               return this;
           }
       }

       public void Add(string key, int value)
       {
           //overload, adds a new keypair
           string strValue = value.ToString();
           this.Add(key, strValue);
       }

       public override string ToString()
       {
           StringBuilder queryString = new StringBuilder();

           foreach (KeyValuePair<string, string> pair in this)
           {
               //we recreate the query from each keypair 
               queryString.Append(pair.Key + "=" + pair.Value + "&");
           }
           //trim the end of the query
           string modifiedQuery = queryString.ToString().TrimEnd("&".ToArray());

           if (this.Count() > 0)
           {
               UriBuilder uriBuild = new UriBuilder(schemeName, hostname);
               uriBuild.Path = path;
               uriBuild.Query = modifiedQuery;
               ammendedUrl = uriBuild.Uri;
               return ammendedUrl.AbsoluteUri;
           }
           else
           {
               return originolUrl.ToString();
           }
       }


       public Uri ToUri()
       {
          this.ToString();
          return ammendedUrl;
       }
   }
}
0 голосов
/ 21 апреля 2009

Я ответил на похожий вопрос некоторое время назад. По сути, лучшим способом было бы использовать класс HttpValueCollection, который на самом деле является свойством QueryString, к сожалению, он является внутренним в фреймворке .NET. Вы можете использовать Reflector, чтобы захватить его (и поместить в свой класс Utils). Таким образом, вы можете манипулировать строкой запроса, например, NameValueCollection, но с учетом всех проблем кодирования / декодирования URL-адреса.

HttpValueCollection расширяет NameValueCollection и имеет конструктор, который принимает зашифрованную строку запроса (включая амперсанды и вопросительные знаки) и переопределяет метод ToString() для последующего перестроения строки запроса из базовой коллекции.

...