En este post aprenderemos de una manera muy sencilla a mostrar varios objetos en una vista en un patrón MVC. Resolveremos la problemática que tiene la propiedad model, cuando precisamos recibir varios objetos en una vista, ya que por defecto sólo es posible recibir un único modelo por vista.

Existen 3 formas para enviar información desde la vista al controlador:

  • ViewData
  • ViewBag
  • Model

Todos ellos, son objetos contenedores que se generan dinámicamente en tiempo de compilación, pero existe alguna diferencia entre ellos:

-ViewData: Es un diccionario de datos de tipo clave-valor.  Un objeto «clave» genera un nuevo elemento para ese objeto.

miobjeto[«clave»]=»valor» – internamente equivale a crear ->  miobjeto.Add(«valor»)

Declarar: ViewData[«nombre»]=»JUAN»;
Recuperar: ViewData[«nombre»];

A través de este tipo de objeto, podemos almacenar cualquier tipo de información y siempre devolverá a la vista un Object, por lo que para obtener el tipo real en la vista precisamos realizar un casting al tipo específico que queramos obtener.

-ViewBag,  también es un diccionario de datos al igual que ViewData, pero en lugar de utilizar cadenas de texto para generar la clave, utiliza propiedades de objeto para almacenar los datos, lo que permite una sintaxis más simple.

Declarar:

ViewBag.propiedad="valor"

Recuperar:

 ViewBag.propiedad

A diferencia de ViewData, éste no necesita realizar un casting para obtener el tipo en la vista.

Tanto ViewBag como ViewData pueden almacenar objetos indefinidos y ser recibidos en la vista , sin embargo, la propiedad Model sólo se puede enviar un objeto a la vista.

Cómo podemos resolver este problema?

Utilizaremos ViewBag como objeto contenedor, ya que es la versión mejorada de ViewData y almacenaremos tantos objetos como queramos.

Práctica:

Realizar una vista en la que aparezca un desplegable con una lista de departamentos a seleccionar. Una vez seleccionado un departamento y pulsado 1 botón , aparecerá en la misma página el listado de empleados que pertenecen a dicho departamento.

enunciado

En nuestro caso, partiremos de un proyecto ya creado que contiene un contexto con las clases que necesitamos utilizar (Empleados y Departamentos).

proy

1.Nos vamos a nuestro modelo y creamos los métodos necesarios para obtener la información de la base de datos. Necesitamos crear un método para listar todos los departamentos una vez cargada la página.

           public List<DEPT> GetDepartamentos()
          {
           var consulta =from datos in contexto.DEPTs select datos;
          return consulta.ToList();
          }

Por otro lado, precisaremos listar los empleados de un determinado departamento una vez seleccionado un departamento.

          public List<EMP> BuscarEmpleadosDepartamento(int deptno)
          {
           var consulta =from datos in contexto.EMPs where datos.DEPT_NO == deptno select datos;
           if (consulta.Count() == 0)
           {
              return null;
            }
           else {
              return consulta.ToList();
           }
        }

2.Creamos un controlador llamado (EmpleadosController). Sobre la carpeta Controller, botón derecho Agregar/Controlador.

3. En la pantalla que aparece a continuación, seleccionamos la opción «Controlador MVC en Blanco«, le nombramos (EmpleadosController) y Aceptar.

4.En el controlador, instanciamos nuestro modelo de datos y nos creamos un nuevo método GET (MultiplesObjetosVistas) para que al cargar la página por primera vez se nos carguen los departamentos. Para ello, recuperamos del modelo los departamentos y los almacenamos en la variable ViewBag.Departamentos.

          //GET: Empleados/MultiplesObjetosVistas
           public ActionResult MultiplesObjetosVistas()
          {
          List<DEPT> listadept =this.modelo.GetDepartamentos();
          ViewBag.Departamentos = listadept;
           return View();
           }

5. Creamos el método Post asociado a la misma vista (MultiplesObjetosVistas). Recibiremos un parámetro en el momento de hacer el submit del formulario que será el identificador del departamento que habremos seleccionado en la lista desplegable. Éste identificador se lo pasaremos al modelo para buscar los empleados que pertenezcan a un determinado departamento.

       //POST: MultiplesObjetosVistas
       [HttpPost]
       public ActionResult MultiplesObjetosVistas(int deptno)
      {
        List<DEPT> listadept =this.modelo.GetDepartamentos();
        ViewBag.Departamentos = listadept;
        List<EMP> listaemp =this.modelo.BuscarEmpleadosDepartamento(deptno);
        return View(listaemp);
      }

En esta ocasión devolveremos la lista de empleados a la vista a través de la propiedad Model.

6.Creamos la vista. Para ello, nos creamos una carpeta llamada (Empleados) en la carpeta Views y le seleccionamos Agregar/Vista vacía..
Una vez dentro en el cuadro de diálogo, damos un nombre a la vista (MultiplesObjetosVistas) y Aceptar.

7. Tipamos el modelo que recibimos en la vista, en nuestro caso la clase (Empleados)

     @model List<ProyectoMVC.Models.EMP>

8. Instanciamos una lista de Departamentos obtenida del ViewBag:

     @{ 
          //LENGUAJE DE SERVIDOR C#
           List<ProyectoMVC.Models.DEPT> listadept =ViewBag.Departamentos;
          }

9. Creamos el formulario con un método post que contenga la lista desplegable y un botón de envío. En la lista desplegable cargamos los distintos departamentos.

 <h2>Multiples Objetos Vistas</h2>

<form method="post">
 <label>Departamentos: </label>
 <select name="deptno" class="form-control">
 @foreach (var dept in listadept)//carga de departamentos
 {
 <option value="@dept.DEPT_NO">
 @dept.DNOMBRE
 </option>
 }
 </select>
 <br/>
 <button type="submit" class="btn-danger">
 Mostrar empleados
 </button>
 </form>

10. Por último, comprobamos si hemos recibido los datos del modelo, si és así, mostramos en una tabla a los empleados.

<hr/>
@if (Model != null)
{
 <table border="1">
 @foreach (var emp in Model)
 {
 <tr>
  <td>@emp.APELLIDO</td>
  <td>@emp.OFICIO</td>
  <td>@emp.SALARIO</td>
 </tr>
 }
 </table>
}

AQUÍ EL CÓDIGO

<EmpleadosController>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MultiplesObjetosVistas.Models;

namespace MultiplesObjetosVistas.Controllers
{
 public class EmpleadosController : Controller
 {
      ModeloDatosHospital modelo;

      public EmpleadosController()
      {
          modelo = new ModeloDatosHospital();
      }

      // GET: Index
      public ActionResult Index()
      {
         return View();
     }

     //GET: MultiplesObjetosVistas
    public ActionResult MultiplesObjetosVistas()
    {
      List<DEPT> listadept =this.modelo.GetDepartamentos();
      ViewBag.Departamentos = listadept;
      return View();
    }

    //POST: MultiplesObjetosVistas
    [HttpPost]
    public ActionResult MultiplesObjetosVistas(int deptno)
   {
     List<DEPT> listadept =this.modelo.GetDepartamentos();
     ViewBag.Departamentos = listadept;
     List<EMP> listaemp =this.modelo.BuscarEmpleadosDepartamento(deptno);
     return View(listaemp);
   }
 }
}

<ModeloHospital>

using MultiplesObjetosVistas.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MultiplesObjetosVistas.Models
{
 public class ModeloDatosHospital
 {
 ContextoHospitalDataContext contexto;

public ModeloDatosHospital()
 {
    this.contexto =new ContextoHospitalDataContext();
 }

public List<EMP> GetEmpleados()
 {
    var consulta =from datos in contexto.EMPs select datos;
    List<EMP> lista = consulta.ToList();
    return lista;
 }
public List<EMP> BuscarEmpleadosDepartamento(int deptno)
 {
 var consulta =from datos in contexto.EMPs where datos.DEPT_NO == deptno select datos;
 if (consulta.Count() == 0)
 {
   return null;
 }
 else {
   return consulta.ToList();
}
 }//método para recuperar todos los departamentos
 public List<DEPT> GetDepartamentos()
 {
 var consulta =
 from datos in contexto.DEPTs
 select datos;
 return consulta.ToList();
 }
}
}

<MultiplesObjetosVistas>

@{
 ViewBag.Title = "MultiplesObjetosVistas";
}

<h2>MultiplesObjetosVistas</h2>
@model List<MultiplesObjetosVistas.Models.EMP>

@{
 //LENGUAJE DE SERVIDOR C#
 List<MultiplesObjetosVistas.Models.DEPT> listadept = ViewBag.Departamentos;
}
<h2>Multiples Objetos Vistas</h2>

<form method="post">
 <label>Departamentos: </label>
 <select name="deptno" class="form-control">
 @foreach (var dept in listadept)
 {
 <option value="@dept.DEPT_NO">
 @dept.DNOMBRE
 </option>
 }
 </select>
 <br />
 <button type="submit" class="btn-danger">
 Mostrar empleados
 </button>
</form>

<hr />
@if (Model != null)
{
 <table border="1">
 @foreach (var emp in Model)
 {
 <tr>
 <td>@emp.APELLIDO</td>
 <td>@emp.OFICIO</td>
 <td>@emp.SALARIO</td>
 </tr>
 }
 </table>
}

A TENER EN CUENTA

  • Siempre que vayamos a recibir un modelo de una petición POST/GET en una vista en la que recibamos parámetros, debemos obligatoriamente preguntar a la vista si existe o no el modelo, ya que no siempre lo vamos a recibir, de lo contrario, generará un error en tiempo de ejecución.«RuntimeBinderException»

Mireia Malonda Mayor
Linkedin
Microsoft MCSD
Tajamar
2016 – 2017

 

 

Leave a Comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.