ASP.NET MVC – Получение Html.BeginForm() для запоминания параметров Querystring при отправке через GET

StackOverflow https://stackoverflow.com/questions/1219223

  •  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.

Дополнительные свойства, отсутствующие в маршруте, будут добавлены в качестве параметров запроса.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top