none
Mantendo o ModelState RRS feed

  • Pergunta

  • Pessoal

    Estou com dificuldades em manter o ModelState, eu tenho uma ActionResult que ao final redireciona o usuário (RedirectToAction); porém caso haja algum problema o ModelState é populado normalmente com os erros tratados porém é perdido durante o redirecionamento.

    Alguém tem idéia de como resolver isso?

    Pesquisando na web vi algo sobre o Patter PRG... e até mesmo um decorator (ExportTempData).. enfim; porém sem sucesso... alguém tem uma luz ai?
    • Movido Leonardo Bruno Lima quarta-feira, 16 de setembro de 2009 18:46 (De:Language Integrated Query - LINQ)
    terça-feira, 15 de setembro de 2009 20:50

Respostas

  • Rodrigo,

    Você poderia fazer da seguinte maneira então.

    public class MyController : Controller
    {
        public ActionResult MyView()
        {
            //Desta forma pelo menos o código não ficou na view.
            ModelStateDictionary ms = (ModelStateDictionary) TempData["ModelState"];
            ViewData.ModelState.Merge(ms);
            return View();
        }
    
        [AcceptVerbs(HttpVerbs.Post)]
        public Actionresult Adicionar(Registro registro)
        {
            if (ModelState.IsValid)
            {
                // processamento
            }
            else
            {
                TempData["ModelState"] = ViewData.ModelState;
            }
    
            // Aqui você chama uma outra Action
            // este action esta com nome de MyView
            // Pode ter alguma confusão conceitual nesse ponto
            return RedirectToAction("MyView");
    
        }
    }
    Mas acredito que você pode estar confundindo os papeis da Controller e da View.

    Este link tem uns videos que falam um pouco destas responsabilidades.


    Espero ter ajudado. Qualquer dúvida favor entrar em contato.

    Douglas Aguiar
    MCAD, MCT
    • Marcado como Resposta RodrigoBraga sexta-feira, 18 de setembro de 2009 14:14
    sexta-feira, 18 de setembro de 2009 13:53
  • Pessoal

    Achei uma solução, estou compartilhando aqui tanto para ajudar outros que possam esbarrar no mesmo problema, bem como discutir se essa é a melhor forma.

    No controller

    if (ModelState.IsValid)
    {
        // processamento
    }
    else
    {
        TempData["ModelState"] = ViewData.ModelState;
    }
    
    return RedirectToAction("MyView");
    e na página (View)
    <%
    	ModelStateDictionary ms = (ModelStateDictionary) TempData["ModelState"];
            ViewData.ModelState.Merge(ms);
    %>
    De acordo com os meus testes aqui, mesmo que você possua N formulários na mesma página você pode processá-los de forma independente; e tratar os erros "isoladamente".

    Achei interessante e relativamente simples; o caminho é esse mesmo?
    • Marcado como Resposta RodrigoBraga quarta-feira, 16 de setembro de 2009 18:50
    quarta-feira, 16 de setembro de 2009 14:36

Todas as Respostas

  • Pessoal

    Achei uma solução, estou compartilhando aqui tanto para ajudar outros que possam esbarrar no mesmo problema, bem como discutir se essa é a melhor forma.

    No controller

    if (ModelState.IsValid)
    {
        // processamento
    }
    else
    {
        TempData["ModelState"] = ViewData.ModelState;
    }
    
    return RedirectToAction("MyView");
    e na página (View)
    <%
    	ModelStateDictionary ms = (ModelStateDictionary) TempData["ModelState"];
            ViewData.ModelState.Merge(ms);
    %>
    De acordo com os meus testes aqui, mesmo que você possua N formulários na mesma página você pode processá-los de forma independente; e tratar os erros "isoladamente".

    Achei interessante e relativamente simples; o caminho é esse mesmo?
    • Marcado como Resposta RodrigoBraga quarta-feira, 16 de setembro de 2009 18:50
    quarta-feira, 16 de setembro de 2009 14:36
  • Rodrigo,

    Não gostei muito desta solução pois você esta colocando lógica na View o que não é legal (temos de nos esforçar ao máximo para deixarmos as views "estupidas"), quanto menos código na View melhor. sua aplicação irá "viver" mais se você tiver isto em mente.

    Você poderia ter feito da seguinte maneira:

    public class MyController : Controller
    {
        public ActionResult Index()
        {
            //Carrega os dados no model da view para
            //exibir uma listagem por exemplo
            return View();
        }
    
        public ActionResult Adicionar()
        {
            //Retorna a view com um form para adicionar um registro
            return View();
        }
    
        [AcceptVerbs(HttpVerbs.Post)]
        public Actionresult Adicionar(Registro registro)
        {
            if (ModelState.IsValid)
            {
                // processamento
                // volta para a listagem
                return View("Index");
            }
            else
            {
                //Retorna a view de adicionar
                //Como o model state estara com erros
                //os mesmos serao exibidos
                return View();
            }
    
        }
    }
    Espero ter ajudado. Qualquer dúvida favor entrar em contato.

    Douglas Aguiar
    MCAD, MCT
    quinta-feira, 17 de setembro de 2009 21:04
  • Aguiar

    Eu realizei alguns testes... e dessa forma o ViewState acaba se perdendo; observe que eu preciso usar o RedirectToAction para continuar "trabalhando".

    Por isso a necessidade de manter o ViewState armazenado no TempData , e na View realizar o merge do ModelState "atual" com o do processamento anterior.
    sexta-feira, 18 de setembro de 2009 12:51
  • Rodrigo,

    Porque você precisa de usar o RedirectToAction?
    E você usa o RedirectToAction para redirecionar para qual view?

    Att,

    Douglas Aguiar
    MCAD, MCT
    sexta-feira, 18 de setembro de 2009 12:55
  • Temos uma página que agrega dois cadastros (cadastro pequenos) e cada uma possui um formulário e submete para ações diferentes, em cada uma delas podem ocorrer erros e por conta disto precisamos devolver o ModelState para a página "central".

    Exemplificando...

    A View XYZ concentra os cadastros de A e B, portanto temos os ActionResults SaveA e SaveB e ambos retornam para a View XYZ (que contem os formulários de entrada de dados).

    Durante o processamente de Save A ou B o ModelState "gerado" não é necessáriamente transportado e "anexado" ao ModelState da View XYZ... acredito  eu, que por conta disto, o ModelState na View XYZ sempre será vazio. Daí a necessidade de durante o processamento de Save A e B, armazenar o ModelState (nestas ações) no TempData para posteriormente realizar o merge com o ModelState na View XYZ, desta forma permitindo que o acesso ao erros em Save A ou B sejam exibidos corretamente.

    sexta-feira, 18 de setembro de 2009 13:16
  • Rodrigo,

    Você poderia fazer da seguinte maneira então.

    public class MyController : Controller
    {
        public ActionResult MyView()
        {
            //Desta forma pelo menos o código não ficou na view.
            ModelStateDictionary ms = (ModelStateDictionary) TempData["ModelState"];
            ViewData.ModelState.Merge(ms);
            return View();
        }
    
        [AcceptVerbs(HttpVerbs.Post)]
        public Actionresult Adicionar(Registro registro)
        {
            if (ModelState.IsValid)
            {
                // processamento
            }
            else
            {
                TempData["ModelState"] = ViewData.ModelState;
            }
    
            // Aqui você chama uma outra Action
            // este action esta com nome de MyView
            // Pode ter alguma confusão conceitual nesse ponto
            return RedirectToAction("MyView");
    
        }
    }
    Mas acredito que você pode estar confundindo os papeis da Controller e da View.

    Este link tem uns videos que falam um pouco destas responsabilidades.


    Espero ter ajudado. Qualquer dúvida favor entrar em contato.

    Douglas Aguiar
    MCAD, MCT
    • Marcado como Resposta RodrigoBraga sexta-feira, 18 de setembro de 2009 14:14
    sexta-feira, 18 de setembro de 2009 13:53
  • Aguiar

    Realmente, com o merge do ModelState no controller fica bem mais elegante :)

    A questão das responsabilidades (View e Controller) acho que eu entendi... vou olhar os vídeos em casa (YouTube travado).

    Valew

    sexta-feira, 18 de setembro de 2009 14:13