martes, 1 de marzo de 2016
Seguro recordaréis que tradicionalmente tanto MVC como Web API han sido frameworks muy guiados por convenciones, es decir, venían de serie diseñados con un conjunto de pautas o normas a las que debíamos ceñirnos si queríamos aprovechar todo su potencial.
Teníamos convenciones para las rutas, de ubicación de vistas, para nombrar los controladores, nombrado de acciones según el verbo HTTP mediante el cual se pretendía acceder a una función del API, y algunas más.
Algunas de estas convenciones se podían cambiar fácilmente usando mecanismos directos proporcionados por los propios frameworks, pero había otras que era bastante más difícil hacerlo y a veces teníamos que hacer auténticos malabarismos con las piezas internas del marco de trabajo para conseguir nuestros objetivos.
ASP.NET Core MVC simplifica bastante la adaptación del framework a nuestras necesidades, proporcionando fórmulas muy potentes para la creación de convenciones personalizadas.
<Disclaimer>En el momento de escribir estas líneas ASP.NET MVC Core 1.0 se encuentra en RC1, por lo que algunos detalles aún pueden variar en la versión final</Disclaimer>
Todo empieza durante el arranque de una aplicación ASP.NET Core MVC, momento en que el framework analiza los ensamblados y crea en memoria un modelo de aplicación, representado por una instancia de clase
ApplicationModel
.En su interior encontramos información muy detallada sobre los filtros definidos, controladores, acciones, rutas, etc. La siguiente captura de pantalla muestra el contenido del
ApplicationModel
de la aplicación MVC Core creada por defecto usando las plantillas de Visual Studio:Y aunque esto ya es bastante interesante de por si, lo que viene ahora es aún mejor: durante el arranque tenemos acceso al
ApplicationModel
y podemos "retocarlo" a nuestro antojo para crear nuestras propias convenciones.¿Y qué tipo de cosas podríamos conseguir con este mecanismo? Pues todas las que nos permita nuestra imaginación: añadir o quitar filtros a controladores en función del criterio que queramos, cambiar nombres de controladores o acciones sobre la marcha, modificar propiedades como los verbos HTTP permitidos, o incluso añadir o eliminar acciones o controladores sobre la marcha (!)
Creación de convenciones personalizadas
Las convenciones personalizadas son clases que implementan el interfazIApplicationModelConvention
, cuyo contrato es el siguiente:public interface IApplicationModelConvention { void Apply(ApplicationModel application); }Durante el arranque, una vez el framework ha terminado de poblar el
ApplicationModel
, invocará a los métodos Apply()
de todas las convenciones que hayan sido registradas, y es ahí donde manipularemos el modelo de aplicación, que nos llegará como parámetro, para adaptarlo a nuestros intereses.El registro de convenciones se realiza desde el método
ConfigureServices()
de la clase Startup
, justo en el momento de añadir MVC al sistema de inyección de dependencias, como se muestra en el siguiente ejemplo. Obviamente, podemos añadir tantas convenciones como queramos:services.AddMvc(options => { options.Conventions.Add(new MyCustomConvention()); options.Conventions.Add(new MyOtherCustomConvention()); });Veamos un ejemplo rápido. La siguiente convención personalizada elimina las acciones de un controlador en las que no se haya indicado expresamente el verbo HTTP a utilizar:
public class NoActionsWithoutVerbsConvention : IApplicationModelConvention { public void Apply(ApplicationModel application) { foreach (var controller in application.Controllers) { var actionsToRemove = controller.Actions .Where(a => !a.HttpMethods.Any()).ToList(); foreach (var action in actionsToRemove) { controller.Actions.Remove(action); } } } }Si registramos esta convención veremos que las acciones declaradas sin atributos como
[HttpGet]
o [HttpPost]
dejarán de existir a todos los efectos. Simplemente hemos recorrido todos los controladores definidos en la aplicación, y hemos obtenido las acciones cuyos métodos HTTP no han sido definidos, eliminándolas a continuación.Otro ejemplo sencillito. La siguiente convención se encargará automáticamente de añadir el filtro
ValidateAntiForgeryToken
a todas las acciones de la aplicación a las que se acceda utilizando el método POST:public class AntiforgeryTokenInPostActionsConvention : IApplicationModelConvention { public void Apply(ApplicationModel application) { var actions = application .Controllers.SelectMany(c => c.Actions) .Where( a => a.HttpMethods.Contains("POST") && !a.Filters.Any(f => f is ValidateAntiForgeryTokenAttribute) ); foreach (var action in actions) { action.Filters.Add(new ValidateAntiForgeryTokenAttribute()); } } }Estoy seguro de que esto de las convenciones dará mucho juego, y sobre todo cuando empecemos a usarlas en el mundo real es cuando descubriremos su auténtico potencial. Pero de momento, la cosa ya promete ;)
Publicado en Variable not found.
Aún no hay comentarios, ¡sé el primero!
Enviar un nuevo comentario