Controladores de ASP.NET MVC

Los controladores son los elementos que forman la capa que actúa como intermediaria entre el modelo y la vista, en la estructura de un proyecto con ASP.NET MVC.
Podemos usar tanto el ejemplo de NHibernate como el de Entity Framework para este ejemplo.
El objetivo de este post será crear un controlador y conocer la forma de asociar las vistas.
En primer lugar, me gustaría eliminar todos los elementos innecesarios que generó la plantilla de ASP.NET MVC:

  • MovieManager/Controllers/HomeController.cs
  • MovieManager/Controllers/AccountController.cs
  • MovieManager/Views/Home
  • MovieManager/Views/Account
  • MovieManager.Tests/Controllers

La creación de estos archivos se puede realizar de una forma automática. Si hacemos click con el botón derecho sobre la carpeta Controllers y nos posicionamos en la opción Add, podremos ver lo siguiente:

Tenemos una nueva opción para crear el elemento Controlador que, en realidad, es una clase que hereda de Controller . Pulsamos sobre ella para crear uno nuevo.

El nombre de un controlador, por convención, se compone de un nombre personalizado + Controller. Cuando tengamos que referirnos a este elemento en alguna parte del código, solamente utilizaremos para nombrarlo el nombre personalizado. En esta ventana, además, se nos sugiere añadir una serie de Actions por defecto, como pueden ser Crear, Actualizar y Detalles. Seleccionamos el checkbox y pulsamos en Add.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

namespace MovieManager.Controllers
{
public class MovieController : Controller
{
//
// GET: /Movie/

public ActionResult Index()
{
return View();
}

//
// GET: /Movie/Details/5

public ActionResult Details(int id)
{
return View();
}

//
// GET: /Movie/Create

public ActionResult Create()
{
return View();
}

//
// POST: /Movie/Create

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection)
{
try
{
// TODO: Add insert logic here

return RedirectToAction("Index");
}
catch
{
return View();
}
}

//
// GET: /Movie/Edit/5

public ActionResult Edit(int id)
{
return View();
}

//
// POST: /Movie/Edit/5

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here

return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}

Este es el código generado por la plantilla, donde solo aparecen una serie de métodos llamados acciones (Actions) los cuales retornan un ActionResult. Existen varios tipos de retorno:

  • ViewResult, renderiza una vista.
  • PartialViewResult, renderiza una vista parcial.
  • RedirectResult, redirige a otra acción del propio controlador.
  • RedirectToRouteResult, redirige a una acción en concreto, especificada en la tabla de rutas, indicando el nombre de la ruta y los parámetro necesarios.
  • ContentResult, devuelve un contenedor definido por el usuario.
  • JsonResult, retorna un objeto JSON.
  • JavaScriptResult, retorna un script para ser ejecutado en el cliente.
  • FileResult, devuelve un archivo como respuesta.
  • EmptyResult, sería equivalente a un resultado nulo.
           

Para mostrar un ejemplo de cómo se implementa una acción, voy a crear las acciones Index y Details.

NHibernate:

//
// GET: /Movie/

public ActionResult Index()
{
var movieRepository = new MovieRepository(MvcApplication.SessionFactory);
return View(movieRepository.ListMovies());
}

//
// GET: /Movie/Details/5

public ActionResult Details(int id)
{
var movieRepository = new MovieRepository(MvcApplication.SessionFactory);
Movie movie = movieRepository.GetMovie(id);
return View(movie);
}

Entity Framework:

//
// GET: /Movie/

public ActionResult Index()
{
var entityFramework = new MovieManagerEntities();
return View(entityFramework.MoviesSet.ToList());
}

//
// GET: /Movie/Details/5

public ActionResult Details(int id)
{
var entityFramework = new MovieManagerEntities();
var movie = (from m in entityFramework.MoviesSet
where m.Id == id
select m).FirstOrDefault();
return View(movie);
}

En  ambos casos estamos devolviendo un ActionResult del tipo Vista, al cual le pasámos como parámetro un objeto(s)  Movie. Para comprender cómo la vista puede interpretar ese objeto, echemos un vistazo a la forma de asociarlas al controlador.


ASOCIACIÓN DE LAS VISTAS

Una vista en ASP.NET MVC corresponde, por convención, a una acción de un controlador. Para crearlas, pulsamos con el botón derecho en una de las acciones.

 

Podemos crear una Vista o bien ir a la que ya tiene asociada. Seleccionamos Add View… para crear una nueva.

Las opciones que nos ofrece son las siguientes:

  • Crear un Partial View, para poder ser reutilizada, para mejorar la experiencia de usuario con AJAX (renderizando solo el contenido de partial view), etc.
  • Crear una vista fuertemente tipada. Significa que nosotros podemos indicarle el tipo de objeto que vamos a mostrar en esta vista. En realidad, la vista heredará del objeto que le digamos.
  • Seleccionar una master page. Por defecto, añadirá la generada por la plantilla en Views/Shared.

En el caso de NHibernate (En Entity framework sería muy similar), selecciono que la clase que voy a utilizar es Movie (MovieManager.Models.Movie). Como Content elijo la opción List, para que me muestre todas las peliculas disponibles. Si en algún momento necesitamos crear una vista con unas características en concreto, podemos seleccionar también Empty para conseguir una vista que herede de la clase pero sin contenido en sí.
Si echamos un vistazo a la cabecera de la vista que vamos a crear sería parecída a la siguiente:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MovieManager.Models.Objects.Movie>>" %>

Vemos que la vista está heredando de la clase Movie y, como además queremos un listado de todas las películas disponibles, nos añade un IEnumerable.

¿Cómo es posible acceder al listado de películas desde la vista? Para ello utilizamos el objeto Model.

<% foreach (var item in Model) { %>

<tr>
<td>
<%= Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) %> |
<%= Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ })%>
</td>
<td>
<%= Html.Encode(item.Id) %>
</td>
<td>
<%= Html.Encode(item.Name) %>
</td>
<td>
<%= Html.Encode(item.Genre) %>
</td>
<td>
<%= Html.Encode(item.Synopsis) %>
</td>
<td>
<%= Html.Encode(String.Format("{0:g}", item.Year)) %>
</td>
</tr>
<% } %>

El objeto Model está almacenando el objeto(s) del cual está heredando nuestra vista.

Por último, para que la acción Details sea funcional necesitamos modificar las líneas donde se utiliza ActionLink. Podemos eliminar sin problemas la establecida para la acción Edit y modificamos Details de la siguiente manera:

<td>
<%= Html.ActionLink("Details", "Details", new { id=item.Id })%>
</td>

Si ahora arrancaramos la aplicación, no tendría sentido que funcionara.

El motivo es porque, al eliminar todos los archivos innecesarios que nombré al principio, no hemos modificado el controlador que se llamará por defecto al arrancar la aplicación. Nos dirigimos al archivo Global.asax y modificamos la ruta por defecto:

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Movie", action = "Index", id = "" } // Parameter defaults
);

}

 

¡Saludos!

4 comentarios en “Controladores de ASP.NET MVC”

  1. Hola Vanesa, muchas gracias por tu comentario 🙂

    En realidad si he trabajado con MVP y puedo decir que le veo numerosas ventajas a MVC en comparación. Por nombrarte algunas, en MVP aún se trabajaba con WebForms, tenías que lidiar con ViewStates, no tenías la facilidad que proporciona el Routing para generar URL amigables (y por lo tanto mejorar la localización de la página). Creo que MVC es el siguiente paso que le podía faltar a MVP 🙂
    Después de trabajar con ambos patrones, creo que MVC genera un código mucho más limpio y claro y, por supuesto, mucho más testeable.

    Espero que pueda servirte,

    ¡Saludos!

Deja un comentario

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