ASP.NET MVC – Получение Html.BeginForm() для запоминания параметров Querystring при отправке через GET
-
10-07-2019 - |
Вопрос
У меня есть форма, отображаемая с помощью Html.BeginForm(), она существует как компонент на главной странице и отображается на каждой странице приложения.Я сделал это, используя Html.RenderAction() из сборки Mvc Futures.Это простая форма поиска, которая обновляет некоторые элементы в том же компоненте под самой формой поиска и выполняет GET, чтобы поисковый запрос появился в строке запроса.
<div class="sideBarContent">
<h2>Search Products</h2>
<% using (Html.BeginForm(ViewContext.RouteData.Values["action"].ToString(),
ViewContext.RouteData.Values["controller"].ToString(), FormMethod.Get)) { %>
<fieldset>
<legend>Search Products</legend>
<div class="formRow">
<label for="ProductsSearch">Search</label>
<%= Html.TextBox("ProductsSearch") %>
</div>
<input type="submit" value="Search" class="button" />
</fieldset>
<% } %>
<ul>
// Products will eventually be listed here
</ul>
</div>
Мне нужна эта форма, чтобы сделать следующее:
1) Он должен выполнить GET для любой текущей страницы, добавив «ProductsSearch» в качестве параметра строки запроса (например. example.com/?ProductsSearch=test или example.com/books/fiction?ProductsSearch=test)
2) Он должен запомнить все существующие параметры строки запроса, которые уже есть в строке запроса, сохраняя их после нажатия кнопки «Поиск», например. example.com/myOrders?page=2 после нажатия кнопки «Поиск» он должен перейти к example.com/myOrders?page=2&ProductsSearch=test)
Я могу это сделать 1) но не могу 2).
Я понимаю, что обычно для перехода от к GET и добавления параметров строки запроса необходимо иметь скрытые поля формы, поэтому я мог бы написать служебную функцию, которая автоматически добавляет кучу скрытых полей формы для любых значений строки запроса, но я хотел проверить, что их нет. Это не более простой подход, или, может быть, я иду неправильным путем.
Ваше здоровье!
Решение
Вам нужно будет использовать метод скрытого поля формы.
Даже если бы вы могли прикрепить всю строку запроса к концу URL-адреса в атрибуте действия тега <form>, браузеры не обращают на это внимания при отправке формы GET.
Ваш метод не слишком сложен;вы хотели бы сделать что-то вроде этого:
public static string QueryStringAsHidden(this HtmlHelper helper)
{
var sb = new StringBuilder();
foreach (var key in HttpContext.Current.Request.QueryString.AllKeys)
{
if (! key.StartsWith("ProductSearch"))
sb.Append(helper.Hidden(key, HttpContext.Current.Request.QueryString[key]));
}
return sb.ToString();
}
Я поместил туда .StartsWith(), потому что вы не хотите находиться на странице поиска и дважды отправлять строку поиска (и теперь вы можете добавлять пейджинговые и другие переменные, специфичные для поиска, с помощью ProductSearch.
Редактировать:ПС:Чтобы форма публиковалась на текущей странице, вам не нужно явно указывать действие и контроллер — вы также можете отправлять значения NULL.
Редактировать2: Зачем вообще беспокоиться о вспомогательном методе?:)
<% HttpContext.Current.Request.QueryString.AllKeys.Where(k => !k.StartsWith("ProductSearch")).ToList().ForEach(k => Response.Write(Html.Hidden(k, HttpContext.Current.Request.QueryString[k]))); %>
Джеймс
Другие советы
Прямой вызов BeginForm() сохраняет значения строки запроса.Любая другая перегрузка имеет тенденцию к сбою.Мне нравится простота использования BeginForm() из моих форм, но мне нужен был способ классифицировать все мои стилизованные формы определенным образом, чтобы не потерять значения строки запроса в действии.
Вот что я придумал:
public static MvcForm BeginNormalForm<T>(this HtmlHelper<T> htmlHelper)
{
var dictionary = new Dictionary<string, object> {{"class", "normal"}};
var rvd = new RouteValueDictionary();
if (htmlHelper.ViewContext.HttpContext != null && htmlHelper.ViewContext.HttpContext.Request != null)
{
foreach (var key in htmlHelper.ViewContext.HttpContext.Request.QueryString.AllKeys)
{
rvd[key] = htmlHelper.ViewContext.HttpContext.Request.QueryString[key];
}
}
var form = htmlHelper.BeginForm(null, null, rvd, FormMethod.Post, dictionary);
return form;
}
Кажется, работает хорошо и сохраняет атрибут моего класса.
Используйте одну из перегрузок BeginForm, которая принимает объект или словарь RouteValues.
Дополнительные свойства, отсутствующие в маршруте, будут добавлены в качестве параметров запроса.