我有一个也可能有查询字符串部分的 URL,查询字符串可能为空或有多个项目。
我想替换查询字符串中的一项,或者如果该项不存在则添加它。
我有一个带有完整 URL 的 URI 对象。
我的第一个想法是使用正则表达式和一些字符串魔法,应该可以。
但这似乎有点不稳定,也许框架有一些查询字符串构建器类?
我有一个也可能有查询字符串部分的 URL,查询字符串可能为空或有多个项目。
我想替换查询字符串中的一项,或者如果该项不存在则添加它。
我有一个带有完整 URL 的 URI 对象。
我的第一个想法是使用正则表达式和一些字符串魔法,应该可以。
但这似乎有点不稳定,也许框架有一些查询字符串构建器类?
我发现这是一个更优雅的解决方案
var qs = HttpUtility.ParseQueryString(Request.QueryString.ToString());
qs.Set("item", newItemValue);
Console.WriteLine(qs.ToString());
让我们有这个网址:
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
我使用以下方法:
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();
}
也许你可以使用这个System.UriBuilder
类。它有一个Query
属性。
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;
这似乎工作得很好。
不,框架没有任何现有的 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
班级。
我使用以下代码附加/替换当前请求 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 原则,你有查询字符串,
string querystring = myURI.Query;
你知道你在寻找什么以及你想用什么来替换它。
所以使用这样的东西: -
if (querystring == "")
myURI.Query += "?" + replacestring;
else
querystring.replace (searchstring, replacestring); // not too sure of syntax !!
不久前我回答了一个类似的问题。基本上,最好的方法是使用HttpValueCollection
该QueryString
属性实际上是的 class ,不幸的是它在 .NET 框架中是内部的。您可以使用 Reflector 来抓取它(并将其放入您的 Utils 类中)。通过这种方式,您可以像 NameValueCollection 一样操作查询字符串,但所有 url 编码/解码问题都会为您处理好。
HttpValueCollection
extends NameValueCollection
,并具有一个构造函数,该构造函数采用编码的查询字符串(包括与号和问号),并且它覆盖了一个ToString()
稍后从基础集合重建查询字符串的方法。
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;
}
}
}