[ASP.NET MVC] (Part I) Controllers
En el patrón Modelo Vista Controlador, la función principal del controlador es responder a los eventos, normalmente producidos por la interacción del usuario con la vista, que pueden o no causar modificaciones en el modelo.
IController Inteface
Para que una clase actue como controlador, como mínimo debe implementar la interfaz IController:
using System;
using System.Web.Routing;
namespace System.Web.Mvc
{
public interface IController
{
void Execute(RequestContext requestContext);
}
}
Vamos a crear nuestro primer controlador implementado esta interfaz, para ello añadimos una nueva clase (Class.cs no Controller) a la carpeta Controllers y sustituiremos por este código:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Geeks.Controllers
{
public class TestController : IController
{
#region IController Members
public void Execute(System.Web.Routing.RequestContext requestContext)
{
requestContext.HttpContext.Response.Write("TestController");
}
#endregion
}
}
Arrancamos la aplicación y probamos:
Una de las peculiaridades de ASP.NET MVC, es lo que se denomina Conventions over Configurations, es decir si aceptamos la norma de nomenclatura en la que todo controlador se identificará <Nombre>Controller, cuando queramos acceder al controlador bastará con utilizar solo el nombre y el Routing se encargará de hacer el resto del trabajo por nosotros, es decir, con esto nos evitamos mantener archivos de configuración, settings...
ControllerBase Class
Es la clase base para la clase Controller, que implementa IController y ademas nos provee de las propiedades TempData y ViewData, que como veremos más adelante nos servirá para enviar los datos a nuestra vista.
Controller Class
Es la clase base para nuestros controladores e implementa la clase ControllerBase
Action Methods
Tendremos que implementar nuestros Action Methods, que son métodos públicos que tienen una correspondencia 1 a 1 con las interacciones del usuario, por ejemplo, teniendo un controlador de productos, tendremos Action Methods para obtener un producto, alta, modificación, borrado…
namespace Geeks.Controllers
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
public class ProductController : Controller
{
public ActionResult Get()
{
return View();
}
public ActionResult Add()
{
return View();
}
public ActionResult Edit()
{
return View();
}
public ActionResult Delete()
{
return View();
}
}
}
Sí ejecutamos http://localhost:1959/Products/Add, nos encontraremos con un error 404, porque cada Action Method de los anteriores debería tener una vista asociada (No siempre tienen porque tener asociada una vista, pero en este caso sí)
Los constructores, propiedades, eventos no pueden actuar cono Action Methods, ni los métodos definidos en la clase Object (Ej: ToString) ni Dispose()…
ActionResult
A simple vista nos puede llamar la atención que todos los Action Methods devuelven un tipo ActionResult:
using System;
namespace System.Web.Mvc
{
// Summary:
// Encapsulates the result of an action method and is used to perform a framework
// level operation on the action method's behalf.
public abstract class ActionResult
{
protected ActionResult();
// Summary:
// Enables processing of the result of an action method by a custom type that
// inherits from System.Web.Mvc.ActionResult.
//
// Parameters:
// context:
public abstract void ExecuteResult(ControllerContext context);
}
}
En el primer ejemplo que vimos cuando implementamos IController, directamente escribiamos un texto a través de Response, pero esto rompe con el término inglés “Separation on Concerns”, es decir, rompemos el concepto de separación por funcionalidad, metemos en el controlador código que debería estar en la vista, por eso está la clase ActionResult y un buen ejemplo es que podemos pasar un ViewResult (Que hereda de ActionResult) a la vista y ella ya tiene el código para formatear y mostrar los datos del producto al usuario, qué por otra parte es la función de la vista:
public ActionResult Get(string id)
{
List<Products> products = SqlRepository.GetProductById(id);
ViewData.Model = products;
return new ViewResult { ViewData = this.ViewData };
}
Y para simplificar código, podemos usar los Helper Methods que nos brinda la clase Controller:
public ActionResult Get(string id)
{
List<Products> products = SqlRepository.GetProductById(id);
return View(products);
}
Existen varios tipos de ActionResult a parte de ViewResult:
| Action Method |
Helper Method |
Descripción |
| ViewResult |
View |
Llama al motor de vistas para renderizar la vista |
| PartialViewReult |
PartialView |
Como ViewResult, pero renderiza una vista parcial. Se usa normalmente en peticiones Ajax |
| RedirectResult |
Redirect |
Redirigir a otro Action Method usando una Url |
| RedirectToRouteResult |
RedirectToAction
RedirectToRoute |
Redirigir a otro Action Method |
| ContentResult |
Content |
Retonar un tipo de contenido definido por el usuario |
| JsonResult |
Json |
Retornar contenido Json |
| JavaScriptResult |
JavaScript |
Retornar código JavaScript |
| FileResult |
File |
Retornar el contenido de un fichero (Binary Output) |
| EmptyResult |
|
No hace nada (Null Object Pattern) |
ActionNameAttribute
Nos permite enmascarar los nombres de los Action Methods, así podemos tener nombres más significativos en nuestro código y más facilmente accesibles a través de Url, por ejemplo:
[ActionName("Get")]
public ActionResult GetProductById(string id)
{
return View();
}
ActionVerbsAttribute
Establece el método HTTP al que responderá el Action Method:
namespace Geeks.Controllers
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
public class ProductController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Edit(string id)
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(string id, FormCollection form)
{
/// Save and Redirect
}
}
}
En la siguiente entrega veremos las vistas.
Salu2