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!
miércoles, 22 de junio de 2016
ASP.NET Core Conforme el desarrollo del nuevo framework ha ido avanzando, se han producido bastantes cambios en el sistema de hosting, que es, al fin y al cabo, quien determina la forma en que podemos cambiarle el nombre a "wwwroot". En el pasado hemos publicado varios posts al respecto (aquí y aquí), y ahora vamos a actualizar los conocimientos tras los cambios aparecidos en la RC2 (sí, esa en la que en teoría no iba a cambiar demasiado respecto a la RC1 ;D).

Estructura de un proyecto ASP.NET Core en Visual Studio, donde aparece la carpeta wwwroot con un icono especialComo sabemos, en proyectos ASP.NET Core, la carpeta "wwwroot", también conocida como "Web root", ejerce como raíz para los contenidos estáticos de la web, es decir, es donde encontraremos todos los archivos que en algún momento enviaremos al lado cliente: javascript, CSS, favicons, imágenes, fonts, etc.

El nombre que se ha dado a la carpeta, "wwwroot", es por convención, y simplemente se trata del valor por defecto establecido por el framework, pero si no nos convence podemos cambiarlo por otro que nos parezca más conveniente. No es que vaya va a ser muy frecuente hacerlo en aplicaciones del mundo real, pero saber que se puede cambiar y cómo hacerlo es interesante porque, además de darnos la libertad de elegir, nos obliga a aprender un poco sobre las interioridades del framework.

Así, si deseamos cambiar el nombre de "wwwoot" por cualquier otro, los pasos serían básicamente tres:
  • Renombrar la carpeta a nivel físico desde el IDE o desde el explorador de archivos.
     
  • Cambiar la configuración de preprocesadores como Gulp, Grunt o WebPack para que utilicen vuestra nueva carpeta como directorio de salida, lo que podemos hacer fácilmente editando sus correspondientes archivos de configuración gulpfile.js, grunt.config, webpack.config.js o el que sea.
     
  • Informar al framework de que esa nueva carpeta es la base para los recursos estáticos, lo que permitirá a otros componentes (por ejemplo, los middlewares encargados de retornar este tipo de contenidos) saber dónde se encuentran los archivos.
En este último punto es donde nos centraremos en el resto del post, viendo algunas fórmulas para conseguirlo.

Establecer la ubicación de los archivos estáticos en ASP.NET Core desde código

Estructura del proyecto, donde hemos renombrado la carpeta "wwwroot" a "_StaticFiles"
Como comentamos hace unas semanas, desde la RC2, los proyectos ASP.NET Core son aplicaciones de consola que incluyen su propio código de arranque en el método estático Main() de la clase Program, en el archivo Program.cs que encontraremos habitualmente en el raíz del proyecto. Desde ahí configuramos el host, el servidor y otros aspectos absolutamente básicos de la aplicación, por lo que es el punto lógico para establecer la ruta donde se encontrarán los archivos estáticos.

Para ello, podemos utilizar el extensor UseWebRoot() de IWebHostBuilder, en el que podemos especificar la ruta, relativa al raíz del proyecto, que usaremos como base para los recursos estáticos. En el siguiente ejemplo establecemos como nombre "_StaticFiles":
public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseWebRoot("_StaticFiles")
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();
        host.Run();
    }
}
Si observáis el código anterior, probablemente os llamará la atención también la llamada a UseContentRoot() que viene incluida por defecto en la plantilla de proyectos ASP.NET Core, y que probablemente pueda dar lugar a confusión porque ContentRoot y WebRoot son cosas distintas:
  • Se denomina "Content root", y se configura mediante la llamada UseContentRoot(), al directorio raíz del proyecto ASP.NET Core. Lo sé, probablemente el nombre no sea muy afortunado, pero es lo que hay  :-/
  • En cambio, "Web root", configurable mediante la llamada a UseWebRoot(), establece la ubicación de los recursos estáticos.
Ambos valores pueden ser obtenidos más adelante por otros componentes accediendo a una instancia de IHostingEnvironment a través del sistema de inyección de dependencias:
public class CheckRoots : Controller
{
    private readonly IHostingEnvironment _env;

    public CheckRoots(IHostingEnvironment env)
    {
        _env = env;
    }

    public ActionResult Index()
    {
        return Content($"ContentRoot: {_env.ContentRootPath}\n" +
                       $"WebRoot:     {_env.WebRootPath}");      
    }
}
El resultado de ejecutar el código anterior accediendo a "/checkroots", podría ser, por ejemplo:
ContentRoot: c:\projects\AspNetCoreRc2App\src\AspNetCoreRc2App
WebRoot:     c:\projects\AspNetCoreRc2App\src\AspNetCoreRc2App\_StaticFiles

Usar un archivo de configuración

Aunque la solución anterior es completamente válida, probablemente veamos más razonable establecer este valor desde un archivo de configuración en lugar de hacerlo directamente desde código.

Si preferimos este enfoque, también será bastante sencillo. En primer lugar, creamos un archivo llamado "hosting.json" en el raíz del proyecto, e introducimos el siguiente contenido:
{
  "webroot": "_StaticFiles"  
}
Ahora hay que indicar al framework que debe cargar este archivo de settings para configurar el host, algo que podemos conseguir con el código mostrado a continuación, correspondiente al fichero  Program.cs:
public class Program
{
    public static void Main(string[] args)
    {
        var currentDir = Directory.GetCurrentDirectory();

        var hostConfiguration = new ConfigurationBuilder()
            .SetBasePath(currentDir)
            .AddJsonFile("hosting.json")
            .Build();

        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(currentDir)
            .UseConfiguration(hostConfiguration)
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();

        host.Run();
    }
}
Estructura del proyecto, donde hemos renombrado la carpeta Veréis que es bastante sencillo, lo único que hemos hecho es obtener y construir un objeto de configuración desde el archivo "hosting.json", y suministrárselo al extensor UseConfiguration() sobre WebHostBuilder.

A partir de ese momento ya estaremos utilizando el valor del parámetro definido en el archivo de configuración para indicar dónde está el raíz del sitio web :)

Además, si os fijáis en la captura de pantalla adjunta, en esta ocasión también el entorno ha reconocido correctamente que "_StaticFiles" es donde se encuentra ahora el raíz del sitio web, mostrándolo con un icono diferente al del resto de directorios del proyecto. Esto es así porque, al menos en el tooling actual, Visual Studio reconoce el contenido del archivo "hosting.json" para obtener este valor.

Por último, observad que aunque aquí hayamos hablado de un archivo de configuración, en realidad estamos utilizando el sistema de configuración de ASP.NET Core, lo que abre la posibilidad a que, sin apenas cambiar el código, podamos utilizar los valores de variables de entorno, settings en memoria o cualquier otra fuente de parámetros de configuración :)

Publicado en Variable not found.

1 comentario:

Anónimo dijo...

Muy buen post! Muy bien explicado! Muchas gracias, saludos desde Arg!