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, 10 de marzo de 2015
ASP.NET MVCHemos comentado en algunas ocasiones que, aparte de la entrada de ASP.NET Core y los cambios en la infraestructura que ello implica, el nuevo MVC incluye también algunas novedades bastante interesantes. Ya estuvimos viendo hace algún tiempo los filtros asíncronos, y hoy vamos a centrarnos en una nueva directiva que podremos utilizar en nuestras vistas Razor a partir de la llegada de la próxima versión del framework.

La novedad en cuestión consiste en la capacidad de añadir a las vistas propiedades cuyo contenido será cargado en tiempo de ejecución usando el motor de inyección de dependencias de ASP.NET 5. o dicho de otra forma, se trata de una implementación de inyección de dependencias en las vistas, componentes en los que hasta ahora eso no era posible, al menos de forma directa y sencilla.

Vamos a verlo en detalle, pero antes, recordad: a día de hoy ASP.NET Core MVC sigue todavía en el horno, y puede que algunas de las cosas que cuente por aquí no sean del todo ciertas para la versión final.

Inyección de dependencias en vistas

Para inyectar dependencias en las vistas, la última versión de Razor nos permitirá utilizar la  nueva directiva @inject como se observa en el siguiente código (.cshtml):

@inject en MVC 6

En el código anterior, la directiva @inject está indicando al motor que debe incluir en la vista una propiedad llamada MyService de tipo IMyService. Cuando esta vista vaya a ser creada, el framework creará una instancia de IMyService utilizando el mecanismo de inyección de dependencias de ASP.NET Core y la introducirá en la propiedad MyService, que estará disponible para su uso directo en el interior de la vista, como se puede observar en la siguiente captura de pantalla:



Fijaos que simplemente para conseguir introducir propiedades personalizadas en la vista en versiones anteriores de ASP.NET MVC teníamos que hacer que ésta heredara de una clase base personalizada, en la que podíamos introducir las propiedades que nos interesaran. Aunque posible, no era una tarea inmediata y requería ciertas labores de “fontanería” para que todo funcionara.

Obviamente, los servicios suministrados a las vistas serán los registrados, como vimos en un post anterior, usando el método ConfigureServices() de la clase de inicialización Startup, por ejemplo así:



Por supuesto, en nuestras vistas podemos tener tantas directivas @inject como necesitemos. De hecho, internamente las vistas están construidas usando este mismo mecanismo, por lo que propiedades que tradicionalmente hemos utilizado en ellas, como  Html o Url, en Core MVC son simplemente propiedades inyectadas de forma similar a lo descrito hasta el momento.

Be DRY, my friend! O cómo utilizar @inject en todas las vistas

Está claro que habrá ocasiones en las que nos vendrá bien inyectar determinados servicios o componentes en todas o parte de las vistas de nuestra aplicación, y cuando esto ocurra probablemente no estemos dispuestos a hacerlo de forma manual sobre ellas.

Hay básicamente dos formas de hacerlo. La primera, muy familiar para los desarrolladores MVC, consiste en agregar las directivas @inject al archivo _ViewStart.cshtml. La única contraindicación que tiene esto es que este archivo sólo se ejecuta en vistas completas, por lo que las vistas parciales o layouts no se verán afectados.

Otra posibilidad más acertada es usar el nuevo archivo _GlobalImports.cshtml. Se trata de una nueva incorporación en Razor que es bastante similar al _ViewStart.cshtml que venimos usando en MVC desde hace años. Su existencia en la carpeta /Views hace que su código se incluya en todas las vistas que se encuentren dentro de la misma jerarquía de directorios, sea cual sea su tipo (parciales, layouts o completas).



Ojo: a día de hoy (marzo 2015), el soporte para el archivo _GlobalImports.cshtml sólo está disponible en las más recientes nightly builds de MVC 6, por lo que para usarlo hay que hacer algunas piruetas.


Nota: en la beta5, el archivo _GlobalImports.cshtml ha sido renombrado a _ViewImports.cshtml.

Y una reflexión: ¿la inyección de dependencias en vistas puede ser peligrosa?

Observad que lo que conseguimos con este nuevo enfoque es hacer que las vistas dejen de ser un componente “pasivo”, que simplemente reciben datos desde el controlador, pasando a ser “activas”, es decir, que ellas mismas soliciten la información que necesiten, cuando la necesiten, para maquetarse. Esto supone un cambio importante respecto a la forma de estructurar las aplicaciones MVC hasta la fecha, donde la práctica habitual era que el controlador se encargara de las relaciones con el modelo.

Oh my god!No puedo negar que la primera vez que vi esta característica, allá por otoño de 2014, los pelos se me pusieron como escarpias pensando en la cantidad de barbaridades que podríamos hacer gracias al uso indebido de ella. Por ejemplo, técnicamente nada impediría que desde una vista se pudiera recibir una referencia a un servicio del modelo, o peor, a un contexto de datos, y utilizarlos para modificar el estado del sistema saltándose por completo la capa Modelo.

Pero tras meditarlo un poco, y aún a falta de ver experiencias reales de uso, tampoco me parece tan terrible, e incluso de hecho se acerca más a las definiciones originales del patrón MVC. Está claro que si alguien se empeña en abrir una base de datos desde una vista, con cualquier versión de MVC habría podido hacerlo sin problema; no era una cuestión técnica la que nos lo impedía, sino las convenciones y patrones a los que decidimos ceñirnos, y esto es algo que descansa más en el terreno conceptual que en aspectos técnicos.

Por tanto, mi conclusión (beta, puede variar ;-D) es que puede ser una característica interesante en determinados escenarios, como para optimizar el rendimiento del servidor. Por ejemplo, hasta ahora, siempre hemos hecho que el controlador cargue desde el modelo toda la información que la vista pueda necesitar, la use o no; es decir, si en la vista hay algún código condicional que decide si muestra o no ciertos datos, puede darse el caso de que parte del trabajo de obtención de datos realizada por el controlador sea en vano. Usando esta característica, podría realizarse la carga sólo si es necesaria. También podría venir bien en conjunción con el flushing asíncrono que acompañará a Core MVC, y del que hablaremos en futuros posts.

Quizás el peligro lo vea no tanto por el uso en sí de esta característica sino por la dispersión que puede crear en el código de acceso a los servicios del modelo. Si hasta ahora podíamos asegurar que todas las llamadas al modelo las realizábamos desde el controlador, en ASP.NET Core MVC también podremos encontrar código de ese tipo en las vistas, y esto puede despistarnos bastante, sobre todo si no tenemos unas directrices claras sobre cuándo usarlo y cuándo no hacerlo.

Publicado en Variable not found.

2 Comentarios:

Unknown dijo...

¿Cual es tu fuente para ver estas novedades de MVC 6?

José María Aguilar dijo...

Hola!

En mis enlaces interesantes encontarás muchas de ellas ;-)

Saludos!