MVC .NET II: Pasando Datos a la View

ForTutorial NET

Este artículo es una continuación, todos los artículos del tutorial aparecerán aquí. Aunque no es necesario, explica la estructura de un proyecto vació y como hacer un hola mundo(aparte de lo que intentaré abarcar en esta «Saga»). En este artículo veremos como pasar datos a la View con .Net de 3 maneras diferentes.

Antes de empezar me gustaría explicar el proyecto que se me ha ocurrido, es un proyecto sencillo.

El proyecto

Básicamente, tendremos libros que estarán relacionados con los autores, editoriales, genero (romance, bélico, misterio, …), Saga ( si pertenece a una saga de libros)
Se que habrán 50.000 gritones de páginas o software, pero es lo que se me ocurrió :). Lo he simplificado para que de momento no haya demasiado.

Iba a hacer una gestión de gastos/ingresos con previsiones, etc, pero se hizo grande y sería denso (y extenso), como para introducirnos en MVC.

Controller – View

Para empezar, veremos como pasar datos entre el controller y la view, para ello creamos un nuevo proyecto de MVC Empty (con el motor de Razor). Yo le he llamado Libreria. Ahora no utilizaremos acceso a BDD, retornaremos datos a «pincho».

Para pasar datos a la View, veremos 3 formas: el ViewBag, ViewData y el ViewModel.

ViewData

El ViewData es un objeto del tipo diccionario (clave – valor) que no requiere instanciarse. Para verlo, crearemos un controller llamado LibrosController con la opción de Empty. Por defecto nos crea una función, el Index pero añadimos una nueva función donde rellenemos este parámetro. Nos tendría que quedar así:

 public ActionResult Datos()
{
   ViewData["Clave"] = "valor";
   return View();
}

Creamos la vista asociada al controller, para ello añadimos un directorio a Views con el nombre del controller (en nuestro caso Libros) y luego la view (Datos.cshtml) y lo dejamos así:

<h2>Datos</h2>

@ViewData["Clave"]

Si ejecutamos nos tendría que salir por pantalla «valor» (para ver esta pagina sería url/controller/funcion, en mi caso http://localhost:2121/libros/datos

Ahora en controller vamos a poner que nos devuelva un listado de libros listado, para ello dejamos la función de datos así:

 
ViewData["Clave"] = new List&lt; Libro&gt;() {
                       new Libro() { Nombre = "Templario", Descripcion = "Novela de templarios"},
                       new Libro() {Nombre ="Legion", Descripcion = "Novela de romanos"}
                   };
return View();

*NOTA* Para crear un listado podemos hacer var x = List< Object>(); y después un .Add(new Object()); o utilizar esta anotación, que es parecida al formato de JSON. Es lo mismo y sobre gustos colores :). **

Si ejecutamos, veremos que no nos imprime lo que queremos, esto es porque recibe un Object y tenemos que castearlo y recorrerlo. Modificamos la View para que muestre lo mismo que en el otro ejemplo:

<h2>Datos</h2>

<table>
  <thead><tr><td>Nombre</td><td>Descripcion</td></tr></thead>
  <tbody>
   @foreach (var lib in (List<mvc_tuto_controller.Models.Libro>) ViewData["Clave"])
   {
     <tr><td>@lib.Nombre</td><td>@lib.Descripcion</td></tr>
   }
  </tbody>
</table>

El problema es que tienes que pasarle la clave como una cadena de texto y si te equivocas, no te enteras hasta que te salta el error. Aparte, tienes que castear el valor en la mayoría de casos.
Si ejecutamos esto, nos mostrara una tabla con los libros.

ViewBag

El Viewbag es muy parecido a el ViewData, es un objeto tipo clave – valor pero se le asigna de manera diferente. Para verlo generamos otra función que quede así:

public ActionResult Cartera()
{
   ViewBag.lstLibros= new List<Libro>() {
                          new Libro() { Nombre = "Templario", Descripcion = "Novela de templarios"},
                          new Libro() {Nombre ="Legion", Descripcion = "Novela de romanos"}
                      };
   return View();
}

Y hacemos la View ( Views/Libros/Cartera.cshtml) que contendrá:

 <h2>Cartera</h2>

<table>
   <thead><tr><td>Nombre</td><td>Descripcion</td></tr></thead>
   <tbody>
   @foreach (var lib in ViewBag.lstLibros)
   {
      <tr><td>@lib.Nombre</td><td>@lib.Descripcion</td></tr>
   }
   </tbody>
</table>

Como podemos ver, en el ViewBag tenemos la propiedad lstLibros, la que hemos añadido en el controller, pero no requiere casteo. En ese aspecto encuentro que esta solución es mas acertada que el ViewData, pero tiene el mismo problema, no te ayuda el intellisense de VS y cuando accedes a la propiedad del ViewBag te puedes equivocar.
Ejecutamos y vemos el mismo resultado que en el otro ejemplo (para verlo, en mi caso sería http://localhost:2121/libros/cartera)

ViewModel

Para pasar los datos a la vista, crearemos una clase vacía en el directorio Models y le llamaremos Libros. Le añadimos como propiedades el Nombre y la Descripcion. Nos tendría que quedar así:

public class Libro
{
   public String Nombre { get; set; }
   public String Descripcion { get; set; }
}

Creamos una nueva función para devolver los libros, tal que:

public ActionResult OModelo()
{
   var lstLibros = new List<Libro>() {
                       new Libro() { Nombre = "Templario", Descripcion = "Novela de templarios"},
                       new Libro() {Nombre ="Legion", Descripcion = "Novela de romanos"}
                   };

   return View(lstLibros);
}

Con esto nos devolvería un listado de libros, para verlo crearemos la view de este controller(Views/Libros/OModelo.cshtml). Modificamos la View para que quede así:

@model List<NOMBRE_PROYECTO.Models.Libro>

<h2>Lista de libros</h2>
<table>
   <thead><tr><td>Nombre</td><td>Descripcion</td></tr></thead>
   <tbody>
   @foreach (var lib in Model)
   {
      <tr><td>@lib.Nombre</td><td>@lib.Descripcion</td></tr>
   }
   </tbody>
</table>

En la primera linea le indicamos que el modelo es nuestra lista de ViewModel de Libro. Después hemos creado una minitabla para que nos muestre el contenido del listado, para ello hemos usado Razor, el @foreach lo que hace es recorrer el listado y los va añadiendo a la tabla.
Ejecutamos la aplicación (en mi caso http://localhost:2121/libros/OModelo) y tendríamos que ver una tabla con los 2 libros.

A mi me gusta más esta última, porque en VS aprovechas el intellisense y como veremos en el siguiente artículo, tiene mas cosas buenas. Eso no quiere decir que no las puedas combinar, puedes devolver un ViewModel y, aparte, rellenar un ViewBag con los parámetros de configuración (por ejemplo).