ASP.Net MVC – ViewData, ViewBag e TempData

ASP.Net MVC – ViewData, ViewBag e TempData entenda as diferenças.

Quando usar ViewData, ViewBag e TempData? Essa é uma das primeiras perguntas que qualquer desenvolvedor faz quando inicia nos aprendizados do ASP.Net MVC.

UPDATE – 13/06 – Adicionando detalhes/correções fornecidos pelo @vcavalcante

Vamos basear nossa explicação conforme a ilustração

ViewData, ViewBag, TempData

Similaridades entre ViewData e ViewBag

ViewData e ViewBag são similares nas seguintes características:

  • São utilizadas para persistir dados entre a Controller e a View correspondente.
  • A duração “tempo de vida” é apenas entre o envio através da Controller e a exibição na View, depois disso tornam-se nulas novamente.
  • No caso de um redirect se tornam nulas.

Diferenças entre ViewData e ViewBag

ViewData ViewBag
É um dicionário de objetos derivado de ViewDataDictionary e é acessível utilizando strings como chaves. É uma propriedade dinâmica baseada na funcionalidade “dynamic” do C# 4.0
Requer typecasting (conversão) quando associada a tipos complexos. Não necessida de conversão para tipos complexos.

Exemplos de aplicação

Controller

public class HomeController : Controller
{
    public ActionResult Index()
    {
        // Meu dado de tipo complexo
        var func = new Funcionario
                        {
                            Nome = "Eduardo Pires",
                            Idade = 31
                        };

        // Propriedades "Dinâmicas"
        ViewBag.Funcionario = func;

        // Modo tradicional
        ViewData["Funcionario"] = func;

        return View();
    }
}

View

@model ProjetoModelo.Models.Funcionario;

@{
    ViewBag.Title = "Exemplo ViewData ViewBag";

    // Necessita de TypeCasting
    var viewDataVariavel = ViewData["Funcionario"] as Funcionario;

    // Não necessita de TypeCasting
    var viewBagVariavel = ViewBag.Funcionario;
}

Resumindo, ViewData e ViewBag possuem a mesma proposta, porém o ViewBag está disponível a partir do ASP.Net MVC 3, enquanto o ViewData existe desde a primeira versão.

OBS: O ViewData é um wrapper, uma implementação do ViewBag, pois utiliza o ViewBag internamente, portanto:

// Criar o ViewBag:
ViewBag.Teste = "Eduardo";

// É o mesmo que criar um ViewData["Teste"],
// pois o ViewData é utilizado internamente. Se chamarmos:

var teste = ViewData["Teste"]; // Teremos teste = "Eduardo";

Por este motivo ViewData é mais rápido que o ViewBag, porém essa diferença de velocidade é mínima, não é necessário deixar de usar o ViewBag por este motivo.

Eu preferencialmente sempre utilizo ViewBag

TempData

  • TempData assemelha-se mais a uma sessão de servidor, porém de curta duração.
  • Possui um tempo de vida maior que o ViewBag e ViewData, o TempData perdura desde sua criação até que seja chamado, ou seja, quando houver um request da informação do TempData, ele se tornará nulo novamente.
  • Uma informação em TempData criada em um Controller persiste após um redirect entre actions (apenas um) e pode ser exibido em sequência em uma View (muito usado em tratamento de erros).
  • Caso não seja chamado o TempData pode manter o estado de seus dados até que a sessão do usuário se encerre.
  • É utilizado para compartilhar informações entre Controllers.
  • O TempData salva suas informações no SessionState do servidor.
  • Após a leitura os dados do TempData são marcados para deleção, ou seja, no final do request todos os dados marcados serão deletados.
  • É um benefício quando necessário transmitir um volume de informações entre as Controllers sem se preocupar em zerar os valores, pois o TempData automaticamente faz isso.

Exemplo de aplicação

Controller

public class HomeController : Controller
{
    [HttpPost]
    public ActionResult CriarFuncionario(Candidato cd)
    {
        // Meu dado de tipo complexo
        var func = new Funcionario
                        {
                            Nome = cd.Nome,
                            Idade = cd.Idade
                        };

        // Pertistir dados até o próximo request.
        TempData["Funcionario"] = func;

        // Redirect entre Controllers
        return RedirectToAction("CriarBeneficiosFuncionario");
    }

    [HttpGet]
    public ActionResult CriarBeneficiosFuncionario()
    {
        // Validando se está vazio
        if (TempData["Funcionario"] != null)
        {
            // Necessário TypeCasting para tipos complexos.
            var func = TempData["Funcionario"] as Funcionario;
        }

        return View();
    }
}

Neste exemplo pudermos entender que o propósito do TempData é compartilhar dados entre Controllers, portanto sua duração persiste até que a informação seja lida.
Outro detalhe é sempre checar se o TempData não está nulo.

Caso você queira manter o dado de um TempData mesmo após a leitura, basta chamar o método Keep(), assim o dado será persistido novamente até a próxima requisição.

// Mantendo o dado do TempData até a próxima leitura (requisição).
TempData.Keep("Funcionario");

// Removendo o dado do TempData desta e da próxima requisição.
TempData.Remove("Funcionario");

Recomenda-se utilizar sempre ViewBag e ViewData para transferência de dados entre Controller e View. O TempData em Views é recomendado no caso de um dado necessitar ser redirecionado entre Actions e posteriormente ser exibido numa View (ViewBag e ViewData são anulados em redirects).
Um caso comum dessa aplicação é no tratamento de erros, veja aqui um exemplo.

Espero ter esclarecido as diferenças e características de ViewData, ViewBag e TempData. Caso tenha alguma dúvida ou queira comentar algo, deixe seu recado logo abaixo 😉

Referências

42 pensou em “ASP.Net MVC – ViewData, ViewBag e TempData

    • Legal Victor!

      Não cheguei a ler seu post antes, mas com certeza é um dado importante para informar.
      Vou dar uma lida, acredito que rola um update aqui 🙂

      Muito obrigado pela contribuição.
      Abraços!

  1. Outra coisa, analisando o seu gráfico eu verifiquei que tem uma informação está faltando, você está demonstrando que tanto a ViewBag quanto a ViewData podem sair do Controller e ir para a View, mas não está demonstrando que o TempData também pode fazer isso.
    Isso é muito utilizado para mensagens de erro por exemplo.
    Eu criei um gist que exemplifica isso: https://gist.github.com/vcavalcante/5762825

    Abraços,

    • Victor,

      Propositalmente quis dar a entender que o TempData deve ser usado para troca de informação entre os Controllers.
      No final do artigo comentei que o TempData não seria recomendado para troca de informação entre Controllers e Views, pois temos ViewBag e ViewData para isso.

      No seu exemplo do gist você usou o TempData para informar um dado da Controller para a View, pois no caso do redirect na action anterior uma ViewBag ou ViewData teriam sido anulados.

      Li o artigo da Rachel Appel (http://www.rachelappel.com/when-to-use-viewbag-viewdata-or-tempdata-in-asp.net-mvc-3-applications) que também deixa claro o uso do TempData nas Views em um cenário igual o que você exemplificou.

      Salvo o caso de um prévio redirect entre actions, Você poderia confirmar se existe alguma recomendação em não usar o TempData de Controllers para Views?

      Mais uma vez obrigado pela colaboração.
      Abraços!

  2. Pela primeira vez vi uma explicação em português boa sobre essa assunto. Obrigado por compartilhar…
    OBS: Se tiver tempo post mais coisas sobre a arquitetura MVC.

  3. Eduardo, parabéns!
    Você tem algum post ou exemplo de como fazer uma aplicação de pedido e item do pedido?

  4. Muito bom este artigo! Serviu para me ajudar a resolver um problemão aqui no projeto!!!
    Parabéns e continue postando…rsrsrsrs…

  5. Pingback: ASP.NET MVC – Acessar ViewBag de dentro da tag script | Wennder Santos

  6. Pingback: ASP.NET MVC – Acessando o conteúdo de um ViewBag de dentro da tag script | Wennder Santos

  7. Pingback: Wennder Santos | Software development and other things.

  8. Eduardo,
    Parabéns pelos esclarecimentos.
    Gostaria de fazer alguns questionamentos no uso destes recursos abordados no seu artigo.
    Quando vou construir qualquer aplicação, gosto sempre de pesquisar melhores práticas adotadas em cada área, seja na arquitetura, usabilidade, etc. E para este assunto, encontrei que o uso de ViewBag e ViewData, em termos de melhores práticas, não era recomendável. A maioria dos artigos recomendam a criação de uma classe de transporte, como um ViewModel, para transacionar objetos e valores entre o Controller e a View. Queria saber o que você acha disso e ao mesmo tempo, saber qual a melhor estratégia para persistir valores de listas no mesmo contexto do Controller para todas as Actions disponíveis.

    • Também estou querendo saber a melhor estratégia para gravar valores de listas, por exemplo se as entidades tiverem relação one-to-many

      • Eduardo, você tem razão! Apesar de ser um bom recurso, não é uma boa prática utilizar desses artificios, uma vez que o MVC propõe um modelo a ser trabalhado na View.
        Também não é rastreável os comportamentos devido os dados manipulados serem dinamicos.
        Nos projetos grandes que participei criávamos TOs para transportá-los até a View.
        Tendo em vista que as entidades não necessariamente precisavam ser subidas até a View.

  9. tenho uma lista de Departamentos que trago da classe dalDepartamentos usando ADONET,
    estou fazendo assim;
    dalDepartamento daoDept = new dalDepartamento();
    List<Departamento dept = daoDept.ListarDept();
    ViewBag.Departametos = dept;

    como retorno esta lista pra View

      • tirou as tags mas vc tem q transformar no mesmo tipo que você colocou na viewbag

        Classe nome = (Classe)ViewBag.NomeViewBag

  10. Bom dia,

    Estou iniciando meus trabalhos com MVC, caso tenham algum artigo para iniciantes, por favor postem.

    abraços

  11. Boa noite,

    Quero retornar para a view e estou fazendo assim:

    14
    Demandas na Qualidade

    @{
    var viewBagVariavel = ViewBag.retornoDemandas;
    }

    Demandas no Desenvolvimento

    Não está funcionando, pode ajudar?
    Grato pela atenção.
    Joelso

Os comentários estão fechados.