替换查询字符串中的项目

时间:2009-04-21 12:08:58

标签: c# asp.net query-string

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

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

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

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

但是看起来有点不稳定,或许框架有一些查询字符串构建器类?

11 个答案:

答案 0 :(得分:42)

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

var qs = HttpUtility.ParseQueryString(Request.QueryString.ToString());
qs.Set("item", newItemValue);
Console.WriteLine(qs.ToString());

答案 1 :(得分:17)

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

答案 2 :(得分: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;

这看起来效果很好。

答案 3 :(得分:4)

我使用以下方法:

    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 :(得分: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班提供。

答案 5 :(得分:3)

也许你可以使用System.UriBuilder课程。它有Query属性。

答案 6 :(得分:2)

我使用以下代码追加/替换当前请求网址中的参数值:

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

答案 7 :(得分:1)

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

string querystring = myURI.Query; 

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

所以使用这样的东西: -

if (querystring == "") 
  myURI.Query += "?" + replacestring; 
else 
  querystring.replace (searchstring, replacestring); // not too sure of syntax !!

答案 8 :(得分:0)

我前一回答similar question。基本上,最好的方法是使用HttpValueCollection属性实际所在的类QueryString,不幸的是它是.NET框架内部的。 您可以使用Reflector来抓取它(并将其放入Utils类中)。这样您就可以像NameValueCollection一样操纵查询字符串,但是所有的url编码/解码问题都会得到照顾。

HttpValueCollection扩展NameValueCollection,并且有一个构造函数,它接受一个编码的查询字符串(包含&符号和问号),并覆盖ToString()方法以便稍后重建查询字符串基础集合。

答案 9 :(得分: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;
       }
   }
}

答案 10 :(得分:-2)

您可以通过预编译来加速RegExps。

查看此tutorial