Как перенаправить POST-запрос на URL, поддерживающий значения модели в MVC - PullRequest
4 голосов
/ 25 июля 2011

У меня довольно стандартная форма сортировки / фильтрации / поиска по страницам, но мне нужен контроль над форматом URL. Все параметры sort / filter / page должны быть частью URL-адреса, чтобы, например, адрес мог быть отправлен кому-либо по электронной почте.

Когда добавляется другой параметр фильтра, выполняется запрос POST. Мой метод контроллера выглядит следующим образом:

[HttpPost]
public ActionResult Search(string filterField,
                           Operator filterOperator, 
                           string filterValue, 
                           PeopleGroupSearchModel model);

PeopleGroupSearchModel заполняется из параметров строки запроса. filter* параметры поступают из опубликованных значений формы.

Я хотел бы проанализировать предоставленные значения фильтров, которые затем добавят фильтр к коллекции в модели с именем Filters. Затем возьмите обновленную модель и преобразуйте ее в соответствующий URL-адрес и передайте его в качестве ответа пользователю.

Так, например, если они есть на этой странице:

PeopleGroup/Search?page=4&sort=Country

... и POST:

  • filterField = PeopleGroupName
  • filterOperator = равно
  • filterValue = Zulu

... как только вся обработка завершена, адрес в их браузере должен выглядеть примерно так:

PeopleGroup/Search?page=4&sort=Country&PeopleGroupName=Zulu&PeopleGroupName_op=Equals

Итак, более или менее то, что я пытаюсь сделать:

[HttpGet]
public ActionResult Search(PeopleGroupSearchModel model)
{
    PeopleGroupData.Search(model);
    ViewData.Model = model;
    return View();
}

[HttpPost]
public ActionResult Search(string filterField,
                           Operator filterOperator,
                           string filterValue,
                           PeopleGroupSearchModel model)
{
    PeopleGroupFilter filter = ParseFilter(filterField, 
                                           filterOperator, 
                                           filterValue);
    model.Filters.Add(filter);
    return RedirectToAction("Search", ???);
}

Я очень новичок в MVC, поэтому, если я пойду совершенно неправильно, пожалуйста, дайте мне знать!

Ответы [ 3 ]

11 голосов
/ 26 июля 2011

Существует несколько возможностей для реализации шаблона Redirect-After-Post (который вам нужен здесь и который является очень хорошим шаблоном IMHO) в ASP.NET MVC:

  1. Использование TempData.В действии POST сохраните модель внутри TempData и перенаправьте:

    TempData["model"] = model;
    return RedirectToAction("Search");
    

    , а затем внутри действия поиска проверьте наличие TempData для извлечения модели:

    PeopleGroupSearchModel model = TempData["model"] as PeopleGroupSearchModel;
    

    Недостатокэтот подход заключается в том, что TempData сохраняется только для одного перенаправления, означающего, что если пользователь нажимает клавишу F5 во время действия Search GET, которое вы ввернули.Это может быть облегчено с помощью сеанса.Но, конечно, сессия представляет другие проблемы масштабируемости.Так что я не фанат этого подхода.

  2. Передать все свойства по запросу:

    return RedirectToAction("Search", new {
        prop1 = model.Prop1,
        prop2 = model.Prop2, 
        ....
    });
    

    Теперь при перенаправлении на действие Search GET механизм связывания модели по умолчанию будетбыть в состоянии восстановить модель.Очевидным недостатком этого подхода является то, что если ваша модель имеет много свойств и даже худшие свойства сложных типов, это может быстро стать громоздким решением.Возможно, вы могли бы сериализовать модель, используя некоторый текстовый формат, такой как JSON, в качестве параметра строки запроса.Конечно, параметры строки запроса ограничены для разных браузеров, так что это также может быть нет-нет.

  3. Сохранить модель в некотором хранилище данных и получить уникальный идентификатор, чтобы впоследствии он мог бытьизвлекается из этого хранилища:

    int id = Persist(model);
    return RedirectToAction("Search", new { id = id });
    

    А затем в действии GET извлекает модель из этого же постоянного хранилища, используя идентификатор.Мне нравится этот подход и я использую его большую часть времени.Если сохранение в вышеупомянутом хранилище данных стоит дорого, вы можете использовать кэширование.

2 голосов
/ 27 июля 2011

Это, вероятно, нарушение принципов MVC, но как только я перестал бороться с фреймворком и просто подумал о том, что я пытался сделать в HTTP-земле, это простое решение работает для меня:

[HttpPost]
public ActionResult Search(PeopleGroupColumn filterField,
                           Operator filterOperator,
                           string filterValue)
{
    var collection =
        HttpUtility.ParseQueryString(Request.QueryString.ToString());
    collection.Set(filterField.ToString(), filterValue);
    collection.Set(filterField.ToString() + "_op", filterOperator.ToString());
    return new RedirectResult(
        Request.Url.AbsolutePath + "?" + collection.ToString());
}
2 голосов
/ 26 июля 2011

Вы можете поместить значения, которые необходимо сохранить, в ControllerContext.RouteData.Values ​​

    public ActionResult TestRedirect()
    {
        RouteValueDictionary routeValues = ControllerContext.RouteData.Values;
        routeValues.Add("Key1","value1");
        routeValues.Add("Key2","value2");

        return RedirectToAction("TargetRedirect", routeValues);
    }

Если вам нужно что-то более общее, вы можете перебрать элементы формы постет.* EDIT

Это выглядело бы как ответ с самым высоким рейтингом здесь: Как сохранить значения строки запроса в asp.net mvc?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...