Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 8 de diciembre de 2009

Controladores en ASP.NET MVCCuando desarrollamos sobre el framework MVC, estamos acostumbrados a crear nuestros controladores partiendo de la clase base Controller, que nos proporciona métodos, propiedades y mecanismos que nos ahorran mucho trabajo en su implementación. Por ejemplo, toda la lógica de localización e invocación de las acciones está definida en esta clase, así como métodos de creación de los tipos más utilizados de ActionResult, las llamadas al model binder, o propiedades de acceso rápido a datos del contexto.

Sin embargo, y es una prueba más de la flexibilidad de diseño del framework, esto no es ni mucho menos obligatorio. La factoría de controladores por defecto no es tan exigente a la hora de localizar estas clases como primer paso durante el proceso de una petición.

Si observamos el código del marco de trabajo, concretamente la clase ControllerTypeCache, nos encontramos con este método estático, responsable de determinar si un tipo dado cumple las condiciones necesarias para ser considerado un controlador válido:

internal static bool IsControllerType(Type t)
{
    return ((((t != null)
             && t.IsPublic) 
             && (t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) 
             && !t.IsAbstract)) 
             && typeof(IController).IsAssignableFrom(t));
}

Como podemos observar, en primer lugar se comprueba que la clase sea pública; es lógico, pues el framework debe instanciarla. A continuación, comprueba que su nombre atienda a la convención de acabar en “Controller” (sí, la convención que aprendimos a desmontar hace algún tiempo ;-)). La siguiente es que no se trate de una clase abstracta, algo básico si pretendemos instanciarla. Por último, se exige que implemente el interfaz IController cuya definición es la siguiente:

public interface IController
{
    void Execute(RequestContext requestContext);
}

Es decir, en ningún caso aparece la clase Controller, ni siquiera la clase ControllerBase, antecesora de la primera. Basta con implementar el método Execute() definido en el interfaz.

Por tanto, cumpliendo estos requisitos podríamos escribir un controlador tan reducido como el siguiente:

using System.Web.Routing;
using System.Web.Mvc;
 
namespace MasterViewModel.Controllers
{
    public class PersonaController : IController
    {
        public void Execute(RequestContext contexto)
        {
            contexto.HttpContext.Response.Write(
                    "Ejecutando la acción " + contexto.RouteData.Values["action"] +
                    " con parámetro " + contexto.RouteData.Values["id"]
            );
        }
    }
}

Incluyendo dicho controlador en un proyecto en el que mantengamos las rutas por defecto, si realizamos una petición del tipo GET /Persona/Beber/Cerveza, obtendremos en el navegador un mensaje como el siguiente:

Resultado de ejecución

Sin embargo, aunque el desarrollo de controladores así de ligeros pueda resultar a priori una idea atractiva  pensando sobre todo en optimizar aún más la velocidad de respuesta, en la práctica no tiene demasiado sentido hacerlo. Sería prácticamente igual de eficiente sobrescribir el método ExecuteCore de la clase Controller, y nos beneficiaríamos de los métodos y propiedades implementados en la misma.

Publicado en: Variable not found.

Aún no hay comentarios, ¡sé el primero!