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 ;)

18 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, 3 de octubre de 2017
ASP.NET CoreAl dar el salto a una nueva tecnología como ASP.NET Core, en muchas ocasiones nos encontramos con el problema de no saber cómo hacer cosas que con las tecnologías tradicionales teníamos completamente controladas. Ya hemos comentado por aquí varios casos (como el Application_Start(), los custom errors o las variables de sesión) y hemos visto cómo se mapean estas funciones al nuevo framework, pero hay muchos más.

Otro ejemplo muy habitual lo encontramos con MapPath(), un método perteneciente a la clase HttpServerUtility de ASP.NET "clásico" que utilizábamos para obtener una ruta física a partir de la ruta virtual o relativa de un recurso. Por ejemplo, en el siguiente código mostramos cómo averiguar la ruta en disco de una imagen utilizando este método:
var path = HttpContext.Current.Server.MapPath("~/images/image.jpg");
// path = C:\inetpub\wwwroot\mysite\images\image.jpg
Pues bien, ni en ASP.NET Core ni en MVC tenemos disponible la clase System.Web.HttpContext, ni por tanto una propiedad Server de tipo HttpServerUtility que usábamos para invocar al método MapPath(). Sin embargo, disponemos de herramientas alternativas que nos permiten conseguir lo mismo, aunque, eso sí, de forma algo menos directa.

La solución más sencilla es utilizar el sistema de inyección de dependencias para obtener una instancia de IHostingEnvironment, a través de la cual podremos obtener el directorio raíz físico del sitio web o, si lo deseamos, de la carpeta configurada como "wwwroot" del mismo. Tras ello, sólo tenemos que componer la ruta final usando métodos clásicos como System.IO.Path.Combine(). En un controlador MVC podría ser algo así:
public class TestController : Controller
{
    private readonly IHostingEnvironment _env;

    public TestController(IHostingEnvironment env)
    {
        _env = env;
    }
    public IActionResult Index()
    {
        var path = Path.Combine(_env.WebRootPath, "images", "image.jpg");
        // path = C:\inetpub\wwwroot\mysite\wwwroot\images\image.jpg
        ...
    }
}
En cambio, si queremos tomar como punto de partida el directorio raíz de la aplicación, que normalmente estará un nivel por arriba de "wwwroot", simplemente debemos usar la propiedad ContentRootPath:
var path = Path.Combine(_env.ContentRootPath, "images", "image.jpg");
// path = C:\inetpub\wwwroot\mysite\images\image.jpg
Observad que al usar Combine() y no concatenaciones o rutas hard-coded, conseguimos que el resultado sea sensible al sistema operativo, por ejemplo en cuanto a los caracteres separadores de carpetas.

Publicado en Variable not found.

4 Comentarios:

Anónimo dijo...

Hola! En el segundo ejemplo creo que el copia pega te ha traicionado, ya que no hay referencia a ContentRootPath.

Aprovecho para dar las gracias por todo tu trabajo, que me ayuda mucho.

José María Aguilar dijo...

Aaarrgg!! Tienes razón, maldito copiapega! ;D

Está solucionado, muchas gracias por avisar y por tus comentarios.

Saludos!

Anónimo dijo...

El asunto es cuando es necesario pasar otras interfaces en el constructor como IOptions o IHttpContextAccessor, el constructor del controller se pone tonto..

José María Aguilar dijo...

Hola!

Pues no debería, son interfaces bastante habituales... ¿qué te ocurre exactamente?

Saludos!