Как RedirectToAction в ASP.NET MVC без потери данных запроса

123

При использовании ASP.NET MVC в некоторых ситуациях (например, при отправке формы) может потребоваться RedirectToAction.

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

Поскольку мне требуется, чтобы форма содержала изначально POSTотредактированные данные, для удобства пользователя, а также в целях проверки, как я могу передать данные через RedirectToAction()? Если я использую параметр viewData, мои POSTпараметры будут изменены на GETпараметры.

Мэтт Митчелл
источник
Вот вопрос, похожий (по той же теме), но отличный от этого. В любом случае, это все еще может быть интересно тем, кто интересуется этим вопросом: http://stackoverflow.com/questions/129335/how-do-you-redirecttoaction-using-post-intead-of-get
Chris Pietschmann,
Почему вы просто не возвращаете то же представление в случае ошибки? RedirectToAction обычно вызывается, если Модель действительна - или мне что-то не хватает ?!
niico

Ответы:

81

Решение состоит в том, чтобы использовать свойство TempData для хранения необходимых компонентов запроса.

Например:

public ActionResult Send()
{
    TempData["form"] = Request.Form;
    return this.RedirectToAction(a => a.Form());
}

Затем в действии «Форма» вы можете:

public ActionResult Form()
{
    /* Declare viewData etc. */

    if (TempData["form"] != null)
    {
        /* Cast TempData["form"] to 
        System.Collections.Specialized.NameValueCollection 
        and use it */
    }

    return View("Form", viewData);
}
Мэтт Митчелл
источник
1
RedirectToAction (a => a.Form ()) не компилируется для меня с использованием MVCv2, вы используете MVCv3?
ChrisAnnODell
1
Это было до MVC1 (2008). Я полагаю, что на каком-то этапе лямбды были удалены (есть проект codeplex MVCContrib, который их повторно вводит, хотя на этом этапе вы также можете использовать их вспомогательный атрибут: stackoverflow.com/questions/1936/… ). В mvc2 вы должны иметь возможность использовать RedirectToAction («Form»), то есть имя в виде строки, хотя я вольно помню, что MVC 2 или 3 представили вспомогательный атрибут, аналогичный тому, что в MVCContrib, если вы хотите пойти на поиск.
Мэтт Митчелл
37

Имейте в виду, что TempData хранит коллекцию форм в сеансе. Если вам не нравится такое поведение, вы можете реализовать новый интерфейс ITempDataProvider и использовать другой механизм для хранения временных данных. Я бы не стал этого делать, если вы не знаете (посредством измерения и профилирования), что использование состояния сеанса вредит вам.

Haacked
источник
13

Взгляните на MVCContrib , вы можете сделать это:

using MvcContrib.Filters;

[ModelStateToTempData]
public class MyController : Controller {
    //
    ...
}
Дэн
источник
8

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

var form = new FooForm();

if (request.UrlReferrer == request.Url)
{
     // Fill form with previous request's data
}

if (Request.IsPost())
{
     if (!form.IsValid)
     {
         ViewData["ValidationErrors"] = ...
     } else {
         // update model
         model.something = foo.something;
         // handoff to post update action
         return RedirectToAction("ModelUpdated", ... etc);
     }
}

// By default render 1 view until form is a valid post
ViewData["Form"] = form;
return View();

Это более или менее закономерно. Немного псевдой. С его помощью вы можете создать 1 представление для обработки рендеринга формы, повторного отображения значений (поскольку форма будет заполнена предыдущими значениями) и отображения сообщений об ошибках.

При публикации этого действия, если он действителен, управление передается другому действию.

Я пытаюсь упростить этот шаблон в среде проверки .NET, поскольку мы создаем поддержку MVC.

Дэйн О'Коннор
источник
Я также использую TempData, проблема, насколько я понимаю, с вашим решением Deeno заключается в том, что если бы пользователь обновил страницу после публикации недействительных данных, он получил бы подтверждение «Вы хотите повторно отправить данные формы». Использование решения TempData, как говорит МэттМитчелл, устраняет эту проблему.
user10479
Прохладно. Кажется, кто-то заметил эту основную идею и в превью 5.
Мэтт Митчелл,
2

Если вы хотите передать данные перенаправленному действию, вы можете использовать следующий метод:

return RedirectToAction("ModelUpdated", new {id = 1});
// The definition of the action method like  public ActionResult ModelUpdated(int id);
lzlstyle
источник
0

TempData - это решение, которое удерживает данные от действия к действию.

Employee employee = new Employee
                {
                        EmpID = "121",
                        EmpFirstName = "Imran",
                        EmpLastName = "Ghani"
                };
                TempData["Employee"] = employee;
Aswal
источник