Как 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 и использовать другой механизм для хранения временных данных. Я бы не стал этого делать, если вы не знаете (посредством измерения и профилирования), что использование состояния сеанса вредит вам.


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);

0

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

Employee employee = new Employee
                {
                        EmpID = "121",
                        EmpFirstName = "Imran",
                        EmpLastName = "Ghani"
                };
                TempData["Employee"] = employee;
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.