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, 1 de octubre de 2019
ASP.NET Core MVC La compilación de vistas y páginas Razor es una de esas features de ASP.NET Core que ha ido dando tumbos y evolucionando a lo largo de las distintas versiones del framework, algunas veces por necesidades técnicas y otras por la búsqueda del funcionamiento más correcto. De hecho, a lo largo de la historia de este blog creo que debe haber pocas cosas de las que haya hablado en tantas ocasiones porque, además, es una característica que me encanta.

Bueno, la cuestión es que en ASP.NET Core 3.0 ha vuelto a cambiar, y esperemos que sea por última vez ;)

Veamos en qué han consistido estos cambios.

Primero: las cosas que no cambian

En ASP.NET Core 3.0, las vistas siguen compilándose cuando deben hacerse estas cosas: en tiempo de compilación. Esto se refleja claramente en la carpeta de binarios, donde, tras compilar, veremos un ensamblado denominado <NombreProyecto>.Views.dll acompañado del correspondiente archivo de símbolos .pdb:

Vistas compiladas en la carpeta de binarios

Además, si examinamos el ensamblado para ver su contenido, podemos observar que en su interior hay clases para cada una de las vistas del proyecto (en este caso, se trata de un proyecto MVC recién creado):

Contenido del archivo Views.dll

Fijaos que no hay nada de Razor ahí; el compilador ha generado una clase para cada vista, y todo lo relativo a su renderizado está implementado en el método ExecuteAsync(). En la captura anterior se puede ver la implementación de uno de esos métodos, y cómo se va generando desde ahí el HTML que se envía al lado cliente.

¿Y qué implica esto? Pues en principio, que para que cualquier cambio en una vista sea tenido en cuenta debemos recompilar el proyecto. Si ejecutamos el proyecto sin depuración o usando dotnet watch run esto no supone ningún problema porque éstas se recompilarán automáticamente cuando sean modificadas, pero es estamos depurando la aplicación sí nos veremos obligados a detener la ejecución y volver a lanzarla.

Otra derivada de la compilación de vistas es que en tiempo de ejecución no es necesario disponer de los archivos .cshtml de las carpetas /Views o /Pages del proyecto, pues todo lo que había en ellas ha sido compilado. Por esta razón, el contenido de dichas carpetas no es incluido por defecto ni en la carpeta de binarios ni al publicar el proyecto.

Obviamente esto tiene sus ventajas, bastante interesantes:
  • Podremos conocer en tiempo de desarrollo si las vistas contienen errores de cualquier tipo, algo que es muy de agradecer ;)
     
  • El paquete de publicación tendrá menos artefactos y, por tanto, podrá la aplicación podrá ser desplegada más rápidamente.
     
  • Dado que las vistas ya están precompiladas, el acceso a las mismas será más rápido desde el primer momento, pues no tienen que volver a pasar por el proceso de compilación.
A cambio, perdemos la interesante posibilidad de realizar pequeños retoques en el código de marcado de una vista o página sin necesidad de compilar y desplegar el proyecto completo.

Novedades: ¿cómo habilitamos la compilación de vistas en runtime?

Con ASP.NET Core 3, esta capacidad es un opt-in, una característica que podemos incluir opcionalmente en nuestras aplicaciones. Para hacerlo, lo primero es añadir el paquete NuGet Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation a nuestro proyecto, y, tras ello, insertar el siguiente código en la configuración de servicios:
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews()
            .AddRazorRuntimeCompilation();
}
Nota: esto también vale si usamos otros sabores del registro de servicios, como AddRazorPages() o AddMvc().
El mero hecho de introducir estas modificaciones en el proyecto ya nos proporcionará ventajas inmediatas, pues podremos modificar las vistas o páginas al vuelo, incluso mientras estamos depurando la aplicación, y podremos ver de forma inmediata los cambios.

Como ya comentamos la última vez que hablamos del tema, esto nos da lo mejor de los dos mundos: inicialmente partimos con la velocidad de ejecución y ventajas de precompilar vistas en tiempo de desarrollo, sin perder la posibilidad de modificarlas en caliente.

Sin embargo, si publicamos el proyecto veremos que las carpetas /Views o /Pages siguen sin incluirse en la carpeta de resultados.

Incluir las vistas y páginas al publicar

Para conseguirlo, sólo tenemos que abrir el archivo .csproj del proyecto e insertar un elemento CopyRazorGenerateFilesToPublishDirectory establecido a true, como se aprecia en el siguiente bloque de código:
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <CopyRazorGenerateFilesToPublishDirectory>
       true
    </CopyRazorGenerateFilesToPublishDirectory>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference 
        Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" 
        Version="3.0.0" />
  </ItemGroup>

</Project>
Publicado en: www.variablenotfound.com.

2 Comentarios:

Jeffer dijo...

Hola amigo, sobre la versión Net Core 3.1 la edición en las vistas igualmente no la toma. He realizado lo que haz descrito en el blog igualmente no lo toma. Agradezco si tienes un enlace o ayuda.

José María Aguilar dijo...

Hola!

Pues debería funcionar, revisa a ver si te dejaste algún paso por detrás. En cualquier caso, puedes echar un vistazo a la documentación oficial, por si ves algo que pudiera faltar.

Saludos!