19

我有一个也可能有查询字符串部分的 URL,查询字符串可能为空或有多个项目。

我想替换查询字符串中的一项,或者如果该项不存在则添加它。

我有一个带有完整 URL 的 URI 对象。

我的第一个想法是使用正则表达式和一些字符串魔法,应该可以。

但这似乎有点不稳定,也许框架有一些查询字符串构建器类?

4

10 回答 10

50

我发现这是一个更优雅的解决方案

var qs = HttpUtility.ParseQueryString(Request.QueryString.ToString());
qs.Set("item", newItemValue);
Console.WriteLine(qs.ToString());
于 2012-05-02T10:44:12.403 回答
26

让我们有这个网址: 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

于 2014-10-15T11:23:17.633 回答
5

我使用以下方法:

    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();
    }
于 2012-02-08T15:03:10.710 回答
4

也许你可以使用这个System.UriBuilder类。它有一个Query属性。

于 2009-04-21T12:33:07.013 回答
4
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;

这似乎工作得很好。

于 2010-10-05T10:45:29.987 回答
3

不,框架没有任何现有的 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班级。

于 2009-04-21T12:21:55.870 回答
2

我使用以下代码附加/替换当前请求 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();
    }
于 2011-10-14T08:34:14.930 回答
1

我同意 Cerebrus 的观点。坚持 KISS 原则,你有查询字符串,

string querystring = myURI.Query; 

你知道你在寻找什么以及你想用什么来替换它。

所以使用这样的东西: -

if (querystring == "") 
  myURI.Query += "?" + replacestring; 
else 
  querystring.replace (searchstring, replacestring); // not too sure of syntax !!
于 2009-04-21T13:46:40.330 回答
0

不久前我回答了一个类似的问题。基本上,最好的方法是使用HttpValueCollectionQueryString属性实际上是的 class ,不幸的是它在 .NET 框架中是内部的。您可以使用 Reflector 来抓取它(并将其放入您的 Utils 类中)。通过这种方式,您可以像 NameValueCollection 一样操作查询字符串,但所有 url 编码/解码问题都会为您处理好。

HttpValueCollectionextends NameValueCollection,并具有一个构造函数,该构造函数采用编码的查询字符串(包括与号和问号),并且它覆盖了一个ToString()稍后从基础集合重建查询字符串的方法。

于 2009-04-21T12:26:50.943 回答
0
   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;
       }
   }
}
于 2015-11-17T11:53:41.760 回答