Como RedirectToAction no asp.net MVC sem perder dados da solicitação

123

Usando o ASP.NET MVC, existem situações (como envio de formulário) que podem exigir a RedirectToAction.

Uma dessas situações é quando você encontra erros de validação após o envio de um formulário e precisa redirecionar de volta para o formulário, mas deseja que o URL reflita o URL do formulário, não a página de ação que ele envia.

Como eu exijo que o formulário contenha os POSTdados originalmente editados, para conveniência do usuário e para fins de validação, como posso passar os dados através do RedirectToAction()? Se eu usar o parâmetro viewData, meus POSTparâmetros serão alterados para GETparâmetros.

Matt Mitchell
fonte
Aqui está uma pergunta que é semelhante (sobre o mesmo tópico), mas diferente deste. De qualquer forma, ainda pode ser de interesse para os interessados ​​nesta questão: http://stackoverflow.com/questions/129335/how-do-you-redirecttoaction-using-post-intead-of-get
Chris Pietschmann
Por que você não está apenas retornando a mesma visualização se houver um erro? RedirectToAction geralmente é chamado se o Modelo for válido - ou estou faltando alguma coisa ?!
Niico 29/04

Respostas:

81

A solução é usar a propriedade TempData para armazenar os componentes de solicitação desejados.

Por exemplo:

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

Em sua ação "Formulário", você pode:

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);
}
Matt Mitchell
fonte
1
RedirectToAction (a => a.Form ()) não é compilado para mim usando o MVCv2, você está usando o MVCv3?
precisa
1
Isso foi pré-MVC1 (2008). As lambdas foram removidas em algum momento, acredito (existe um projeto MVCContrib do codeplex que as reintroduz, embora você também possa usar o atributo helper nesse estágio: stackoverflow.com/questions/1936/… ). No mvc2, você deve conseguir RedirectToAction ("Form"), ou seja, nome como uma string, embora eu me lembre vagamente que o MVC 2 ou 3 introduziu um atributo auxiliar semelhante ao do MVCContrib, se você deseja pesquisar.
Matt Mitchell
37

Lembre-se de que TempData armazena a coleção de formulários na sessão. Se você não gostar desse comportamento, poderá implementar a nova interface ITempDataProvider e usar algum outro mecanismo para armazenar dados temporários. Eu não faria isso, a menos que você saiba de fato (via medição e criação de perfil) que o uso do estado Session está prejudicando você.

Haacked
fonte
13

Dê uma olhada no MVCContrib , você pode fazer isso:

using MvcContrib.Filters;

[ModelStateToTempData]
public class MyController : Controller {
    //
    ...
}
Dan
fonte
8

Existe outra maneira que evita tempdata. O padrão que eu gosto envolve a criação de 1 ação para a renderização original e a renderização novamente do formulário inválido. É algo como isto:

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

Esse é o padrão mais ou menos. Um pouco de pseudoy. Com isso, você pode criar 1 visualização para manipular a renderização do formulário, exibindo novamente os valores (já que o formulário será preenchido com valores anteriores) e mostrando mensagens de erro.

Quando o lançamento nesta ação, se for válido, ele transfere o controle para outra ação.

Estou tentando facilitar esse padrão na estrutura de validação .net à medida que desenvolvemos o suporte ao MVC.

Dane O'Connor
fonte
Também uso TempData, o problema como o entendo, com a sua solução Deeno, é que, se o usuário atualizar a página após postar dados inválidos, receberá uma confirmação "Deseja reenviar os dados do formulário". Usar a solução TempData como MattMitchell diz elimina esse problema.
user10479
Legal. Parece que alguém notou essa idéia básica também na pré-visualização 5.
Matt Mitchell
2

Se você deseja passar dados para a ação redirecionada, o método que você pode usar é:

return RedirectToAction("ModelUpdated", new {id = 1});
// The definition of the action method like  public ActionResult ModelUpdated(int id);
lzlstyle
fonte
0

TempData é a solução que mantém os dados de ação em ação.

Employee employee = new Employee
                {
                        EmpID = "121",
                        EmpFirstName = "Imran",
                        EmpLastName = "Ghani"
                };
                TempData["Employee"] = employee;
Aswal
fonte