Изменить значение строки запроса одиночного URL-адреса
У меня есть страница ASP.NET, которая принимает ряд параметров в строке запроса:
search.aspx?q=123&source=WebSearch
Это отобразит первую страницу результатов поиска. Теперь, в рамках рендеринга этой страницы, я хочу отобразить набор ссылок, которые позволяют пользователю переходить на разные страницы в результатах поиска. Я могу сделать это просто append &page=1
или &page=2
и т.д.
Там, где это усложняется, я хочу сохранить строку входных запросов на исходной странице для каждого параметра, кроме той, которую я пытаюсь изменить. Могут быть другие параметры в URL-адресе, используемом другими компонентами, и значение, которое я пытаюсь заменить, может или не может быть определено:
search.aspx?q=123&source=WebSearch&page=1&Theme=Blue
В этом случае для создания ссылки на следующую страницу результатов я хочу изменить page=1
на page=2
, оставив остальную строку запроса без изменений.
Есть ли встроенный способ сделать это, или мне нужно выполнить всю парсинг/рекомбинацию строк вручную?
Ответы
Ответ 1
Вы не можете изменить 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
возвращает NameValueCollection
(на самом деле он действительно возвращает HttpValueCollection
, который кодирует результаты, как я упоминаю в ответе на другой вопрос). Затем вы можете использовать метод 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
.
Ответ 2
Вы можете сделать это без всех накладных расходов на перенаправление (что не является незначительным). Мое личное предпочтение - работать с 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);
Ответ 3
Используя этот класс-помощник QueryStringBuilder, вы можете захватить текущую QueryString и вызвать метод Add
для изменения существующей пары ключ/значение...
//before: "?id=123&page=1&sessionId=ABC"
string newQueryString = QueryString.Current.Add("page", "2");
//after: "?id=123&page=2&sessionId=ABC"
Ответ 4
Используйте URIBuilder В частности, текст ссылки Свойство запроса
Я считаю, что делает то, что вам нужно.
Ответ 5
Это довольно произвольно, по крайней мере, в .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>