> Manuales > Manual del framework ASP.NET MVC

En este artículo vamos a ver como pasar datos desde los controladores a las vistas.

Hay tres métodos (que realmente son dos) principales para pasar datos de los controladores a las vistas.

Recordad que según el patrón MVC, el controlador es quien accede al modelo para obtener los datos y mandárselos a la vista. La vista debe limitarse a mostrar esos datos (o a pedir datos nuevos y mandárselos de vuelta al controlador, lo que veremos más adelante). Los datos que el modelo proporciona al controlador pueden venir de cualquier fuente (usualmente una base de datos).

Primer método: ViewData

El primero de los métodos es el denominado ViewData. ViewData es un diccionario de clave (una cadena) - valor (un objeto) que el controlador pasa a la vista. Un ejemplo de uso de ViewData es el siguiente controlador:

public class HomeController : Controller
{
public ActionResult Index()
{
ViewData["Nombre"] = "Eduard Tomàs";
ViewData["Twitter"] = "eiximenis";
return View();
}

}

Aquí se define el controlador Home con la acción Index (recordad que las acciones son los métodos públicos que reciben las peticiones del navegador). En esta acción establecemos las claves Nombre y Twitter del ViewData y luego devolvemos la vista asociada a dicha acción.

Para mostrar los datos en la vista, simplemente usamos la propiedad ViewData que tienen las vistas y que funciona exactamente igual. En este caso, en el código de nuestra vista (archivo Home.cshtml que estaría en la carpeta Home dentro de la carpeta Views) tendríamos algo como:

<h2>Index</h2>

Mi nombre es @ViewData["Nombre"] y puedes seguirme en
<a href="http://twitter.com/@ViewData["Twitter"]">Twitter</a>.

Fijaos en dos cosas:

  1. Para acceder a un valor del ViewData, simplemente usamos ViewData["clave"].
  2. Y muy importante: el uso de la arroba (@) antes de llamar a ViewData. Eso es parte de la sintaxis Razor (que veremos con detalle más adelante, así que de momento no nos vamos a preocupar mucho de ella).
El uso de ViewData tiene dos puntos débiles que deben tenerse presentes:
  1. Las claves son cadenas, por lo que si nos equivocamos el compilador no puede ayudarnos. Tampoco herramientas de refactoring pueden darnos soporte.
  2. ViewData["clave"] siempre devuelve un object por lo que debemos ir haciendo casting si queremos obtener el tipo real de lo que hay almacenado.
P.ej. En un controlador ponemos el siguiente valor en ViewData:

ViewData["FechaAlta"] = new DateTime(2008, 12, 10);

Este valor es un DateTime, no obstante si desde la vista queremos llamar a los métodos de DateTime (como ToLongDateString()) deberemos hacer un casting:

Dado de alta en: @(((DateTime)ViewData["FechaAlta"]).ToLongDateString())

Si no hiciéramos el casting a DateTime, la llamada a ToLongDateString() generaría una excepción (aun cuando, en efecto, lo que hay en el ViewData["FechaAlta"] es un DateTime).

Segundo método: ViewBag

ViewBag funciona de forma muy parecida a ViewData. Al igual que ViewData, ViewBag es un diccionario de clave - valor. Pero se aprovecha de las capacidades de programación dinámica que ofrece C# 4, para en lugar de usar cadenas para especificar la clave, usar propiedades. Así, desde una acción podemos hacer:

public ActionResult Index2()
{
ViewBag.Nombre = "Eduard Tomàs";
ViewBag.Twitter = "eiximenis";
ViewBag.FechaAlta = new DateTime(2008, 12, 10);
return View();
}

Fijaos que el código es casi igual al uso de ViewData, solo que en lugar de hacer ViewData["clave"] hacemos ViewBag.clave.

Y para recuperarlos desde una vista? Pues igual que antes, podemos usar la propiedad ViewBag:

<h2>Index2</h2>

Mi nombre es @ViewBag.Nombre y puedes seguirme en
<a href="http://twitter.com/@ViewBag.Twitter">Twitter</a>. <br />
Dado de alta en: @ViewBag.FechaAlta.ToLongDateString()

Aquí podemos ver la gran ventaja de ViewBag respecto ViewData: no es necesario usar casting. Fijaos que para usar ToLongDateString() no hemos tenido necesidad de convertir el resultado devuelto por ViewBag.FechaAlta a DateTime. Esa es la gran ventaja de ViewBag respecto a ViewData y es por eso que, personalmente, os recomiendo usar ViewBag en lugar de ViewData (de hecho ViewData se mantiene por compatibilidad con las versiones anteriores del framework de ASP.NET MVC). Otra ventaja es que no usamos cadenas sino propiedades para acceder a los elementos, pero ojo, que el compilador no puede ayudaros si accedéis a una clave (propiedad) que no existe (al ser las propiedades dinámicas).

Tercer método: Model (también conocido como ViewModel)

El tercer método para pasar información de una acción de un controlador a una vista, es usando la propiedad Model. La propiedad Model no funciona como las anteriores, sino que lo que se pasa es un objeto, que se manda de la acción hacia la vista.

A diferencia de ViewData y ViewBag que existen tanto en el controlador como en la vista, el controlador no tiene una propiedad Model. En su lugar se usa una sobrecarga del método View() y se manda el objeto como parámetro:

public class Usuario
{
public string Nombre { get; set; }
public string Twitter { get; set; }
public DateTime Alta { get; set; }
}

public class HomeController : Controller
{
public ActionResult Index3()
{
Usuario data = new Usuario();
data.Nombre = "Eduard Tomàs";
data.Twitter = "eiximenis";
data.Alta = new DateTime(2008, 12, 10);
return View(data);
}
}

Notemos las diferencias: El controlador crea un objeto de la clase Usuario y manda ese objeto a la vista, pasándolo como parámetro a la función View.

¿Y desde la vista? Pues usamos la propiedad Model para acceder a dicho objeto:

@model MvcHelloWorld.Controllers.Usuario

<h2>Index3</h2>
Mi nombre es @Model.Nombre y puedes seguirme en
<a href="http://twitter.com/@Model.Twitter">Twitter</a>. <br />
Dado de alta en: @Model.Alta.ToLongDateString()

Fijaos que ahora usamos Model para acceder a los datos, en lugar de ViewData o ViewBag. Y una cosa importante: fijémonos en la primera línea, que empieza con @model. Esa línea le indica al framework de que tipo es el objeto que la vista recibe del controlador (es decir, de que tipo es la propiedad Model). Por supuesto este tipo debe coincidir con el objeto que se pasa como parámetro a la función View en la acción del controlador. Una nota: El uso de @model es opcional, si no lo ponemos, nuestra vista puede seguir usando la propiedad Model, pero en este caso es de tipo dynamic. Eso tiene sus ventajas y sus inconvenientes (volveremos sobre ello en posteriores artículos). Las vistas que declaran @model, se llaman vistas fuertemente tipadas. Usar vistas fuertemente tipadas tiene una ventaja que es que al saber Visual Studio cual es el tipo de la propiedad Model, nos puede proporcionar soporte de Intellisense.

Usar este mecanismo es la manera preferida de pasar datos desde una acción a una vista (ya que en lugar de tener datos desperdigados en n claves los podemos tener organizados en una clase). A las clases que se pasan desde las acciones a las vistas (como nuestra clase Usuario) se les conoce también con el nombre de ViewModels (para distinguirlas de las clases que conforman el Modelo del patrón MVC, ya que los ViewModels lo único que hacen es contener datos que mostrará una vista).

Una nota final

Al principio del artículo he comentado que veríamos tres métodos que en realidad eran dos. ¿A que me refería? Pues básicamente a que ViewBag y ViewData son dos maneras distintas para acceder al mismo conjunto de datos. Es decir, si establecemos el valor de ViewData["Nombre"] podemos leerlo con ViewBag.Nombre y viceversa. De ahí que haya comentado que eran tres métodos, que realmente eran dos. Para más información os recomiendo el artículo de José M. Aguilar sobre el tema, que podéis leer en: http://www.variablenotfound.com/2010/12/viewbag-en-aspnet-mvc-3.html

Un saludo a todos!
PD: Comentaros solamente que el código fuente de todos los artículos de esta serie sobre ASP.NET MVC lo podréis encontrar en: http://cid-6521c259e9b1bec6.office.live.com/browse.aspx/desarrolloweb-aspnetmvc

Eduard Tomàs

Apasionado de la informática, los videojuegos, rol y... la cerveza. Key Consulta...

Manual