替换查询字符串中的项目
我有一个URL也可能有一个查询字符串部分,查询字符串可能是空的或有多个项目。
我想替换查询字符串中的一个项目,或者如果该项目尚不存在则添加它。
我有一个带有完整URL的URI对象。
我的第一个想法是使用正则表达式和一些字符串魔法,应该这样做。
但它似乎有点摇摇欲坠,也许框架有一些查询字符串构建器类?
也许你可以使用System.UriBuilder
类。 它有一个Query
属性。
我发现这是一个更优雅的解决方案
var qs = HttpUtility.ParseQueryString(Request.QueryString.ToString()); qs.Set("item", newItemValue); Console.WriteLine(qs.ToString());
让我们有这个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
属性以生成具有更改的param值的新uri。
var uriBuilder = new UriBuilder(uri); uriBuilder.Query = qs.ToString(); var newUri = uriBuilder.Uri;
现在你在newUri
这个值: https://localhost/video?param1=newValue2
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;
这似乎工作得很好。
我使用以下方法:
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(); }
不,该框架没有任何现有的QueryStringBuilder类,但通常HTTP请求中的查询字符串信息可通过Request.Querystring
属性作为可迭代和可搜索的NameValueCollection
提供。
但是,由于您是从Uri
对象开始的,因此需要使用Uri
对象的Query
属性获取查询字符串部分。 这将产生一个forms的字符串:
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
类。
我使用以下代码在当前请求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(); }
我同意Cerebrus。 坚持KISS原则,你有querystring,
string querystring = myURI.Query;
你知道你在寻找什么以及你想要用它替换它。
所以使用这样的东西: –
if (querystring == "") myURI.Query += "?" + replacestring; else querystring.replace (searchstring, replacestring); // not too sure of syntax !!
我刚才回答了类似的问题 。 基本上,最好的方法是使用类HttpValueCollection
,它实际上是QueryString
属性,不幸的是它在.NET框架中是内部的。 您可以使用Reflector来抓取它(并将其放入Utils类中)。 这样您就可以像NameValueCollection一样操纵查询字符串,但是所有的url编码/解码问题都会得到照顾。
HttpValueCollection
扩展了NameValueCollection
,并且具有一个构造函数,该构造函数接受编码的查询字符串(包括&符号和问号),并且它会覆盖ToString()
方法,以便稍后从底层集合重建查询字符串。
public class QueryParams : Dictionary { 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 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; } } }
您可以通过预编译来加速RegExps。
看看这个教程