我有一个ASP.NET页面,它在查询字符串中包含许多参数:
search.aspx?q=123&source=WebSearch
这将显示搜索结果的第一页。现在,在该页面的呈现中,我想显示一组链接,允许用户跳转到搜索结果中的不同页面。我只需附加&page=1
或&page=2
等
它变得复杂的是我想保留原始页面中的输入查询字符串,除了我正在尝试更改的参数之外的每个参数。其他组件使用的url中可能还有其他参数,我尝试替换的值可能已经定义过,也可能没有定义:
search.aspx?q=123&source=WebSearch&page=1&Theme=Blue
在这种情况下,要生成指向下一页结果的链接,我希望将page=1
更改为page=2
,同时保持查询字符串的其余部分不变。
是否有内置方法可以执行此操作,还是需要手动执行所有字符串解析/重组?
答案 0 :(得分:53)
您不能直接修改QueryString,因为它是只读的。您需要获取值,修改它们,然后将它们重新组合在一起。试试这个:
var nameValues = HttpUtility.ParseQueryString(Request.QueryString.ToString());
nameValues.Set("page", "2");
string url = Request.Url.AbsolutePath;
string updatedQueryString = "?" + nameValues.ToString();
Response.Redirect(url + updatedQueryString);
ParseQueryString
method会返回NameValueCollection
(实际上它确实会返回HttpValueCollection
,对结果进行编码as I mention in an answer to another question)。然后,您可以使用Set
方法更新值。您还可以使用Add
方法添加新方法,或Remove
删除值。最后,在名称ToString()
上调用NameValueCollection
将以name1=value1&name2=value2
querystring ready格式返回名称值对。一旦你将它附加到URL并重定向。
或者,您可以使用索引器添加新密钥或修改现有密钥:
nameValues["temp"] = "hello!"; // add "temp" if it didn't exist
nameValues["temp"] = "hello, world!"; // overwrite "temp"
nameValues.Remove("temp"); // can't remove via indexer
您可能需要添加using System.Collections.Specialized;
才能使用NameValueCollection
类。
答案 1 :(得分:12)
你可以在没有重定向的所有开销的情况下做到这一点(这是不可忽视的)。我个人的偏好是使用NameValueCollection,它实际上是查询字符串,但使用反射:
// reflect to readonly property
PropertyInfo isReadOnly = typeof(System.Collections.Specialized.NameValueCollection).GetProperty("IsReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
// make collection editable
isReadOnly.SetValue(this.Request.QueryString, false, null);
// remove
this.Request.QueryString.Remove("foo");
// modify
this.Request.QueryString.Set("bar", "123");
// make collection readonly again
isReadOnly.SetValue(this.Request.QueryString, true, null);
答案 2 :(得分:5)
使用此QueryStringBuilder helper class,您可以获取当前的QueryString并调用Add
方法来更改现有的键/值对...
//before: "?id=123&page=1&sessionId=ABC"
string newQueryString = QueryString.Current.Add("page", "2");
//after: "?id=123&page=2&sessionId=ABC"
答案 3 :(得分:0)
使用URIBuilder特别是link text查询属性
我相信你能做到你需要的。
答案 4 :(得分:0)
这至少在.NET Core中非常随意。这一切归结为asp-all-route-data
考虑以下简单示例(取自" paginator"我在几乎每个项目中使用的视图模型):
public class SomeViewModel
{
public Dictionary<string, string> NextPageLink(IQueryCollection query)
{
/*
* NOTE: how you derive the "2" is fully up to you
*/
return ParseQueryCollection(query, "page", "2");
}
Dictionary<string, string> ParseQueryCollection(IQueryCollection query, string replacementKey, string replacementValue)
{
var dict = new Dictionary<string, string>()
{
{ replacementKey, replacementValue }
};
foreach (var q in query)
{
if (!string.Equals(q.Key, replacementKey, StringComparison.OrdinalIgnoreCase))
{
dict.Add(q.Key, q.Value);
}
}
return dict;
}
}
然后在您的视图中使用,只需从Context.Request
传递当前请求查询集合的方法:
<a asp-all-route-data="@Model.NextPageLink(Context.Request.Query)">Next</a>