Как получить абсолютный путь в альтернативном пути ASP.Net Core для Server.MapPath

Как получить абсолютный путь в альтернативном Server.MapPath ASP для Server.MapPath

Я попытался использовать IHostingEnvironment но он не дает правильного результата.

IHostingEnvironment env = new HostingEnvironment();
var str1 = env.ContentRootPath; // Null
var str2 = env.WebRootPath; // Null, both doesn't give any result 

У меня есть один файл изображения (Sample.PNG) в папке wwwroot. Мне нужно получить этот абсолютный путь.

Ответ 1

IHostingEnvironment в качестве зависимости в зависимый класс. Фреймворк заполнит его для вас

public class HomeController : Controller {
    private IHostingEnvironment _hostingEnvironment;

    public HomeController(IHostingEnvironment environment) {
        _hostingEnvironment = environment;
    }

    [HttpGet]
    public IActionResult Get() {
        var path = Path.Combine(_hostingEnvironment.WebRootPath, "Sample.PNG");
        return View();
    }
}

Вы можете пойти еще дальше и создать свою собственную абстракцию и реализацию службы провайдера пути.

public interface IPathProvider {
    string MapPath(string path);
}

public class PathProvider : IPathProvider {
    private IHostingEnvironment _hostingEnvironment;

    public PathProvider(IHostingEnvironment environment) {
        _hostingEnvironment = environment;
    }

    public string MapPath(string path) {
        var filePath = Path.Combine(_hostingEnvironment.WebRootPath, path);
        return filePath;
    }
}

И внедрить IPathProvider в зависимые классы.

public class HomeController : Controller {
    private IPathProvider pathProvider;

    public HomeController(IPathProvider pathProvider) {
        this.pathProvider = pathProvider;
    }

    [HttpGet]
    public IActionResult Get() {
        var path = pathProvider.MapPath("Sample.PNG");
        return View();
    }
}

Обязательно зарегистрируйте службу в контейнере DI

services.AddSingleton<IPathProvider, PathProvider>();

Ответ 2

* Hack * Не рекомендуется, но к вашему сведению вы можете получить абсолютный путь из относительного пути с помощью var abs = Path.GetFullPath("~/Content/Images/Sample.PNG").Replace("~\\","");

Предпочитаю подходы DI/Service выше, но если вы находитесь в ситуации, не связанной с DI (например, класс, созданный с помощью Activator), это будет работать.

Ответ 3

Лучшим решением является использование IFileProvider.GetFileInfo().

    public IActionResult ResizeCat([FromServices] IFileProvider fileProvider)
    {
        // get absolute path (equivalent to MapPath)
        string absolutePath = fileProvider.GetFileInfo("/assets/images/cat.jpg").PhysicalPath;  
        ... 
    }

Вы должны зарегистрировать IFileProvider как это, чтобы иметь доступ к нему через DI:

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc();

        var physicalProvider = _hostingEnvironment.ContentRootFileProvider;
        var embeddedProvider = new EmbeddedFileProvider(Assembly.GetEntryAssembly());
        var compositeProvider = new CompositeFileProvider(physicalProvider, embeddedProvider);

        // choose one provider to use for the app and register it
        //services.AddSingleton<IFileProvider>(physicalProvider);
        //services.AddSingleton<IFileProvider>(embeddedProvider);
        services.AddSingleton<IFileProvider>(compositeProvider);
    }

Как вы можете видеть, эта логика (для чего происходит файл) может стать довольно сложной, но ваш код не сломается, если он изменится.

Вы можете создать пользовательский IFileProvider с new PhysicalFileProvider(root) IFileProvider new PhysicalFileProvider(root) если у вас есть специальная логика. У меня была ситуация, когда я хочу загрузить изображение в промежуточное программное обеспечение, изменить его размер или обрезать. Но это проект Angular, поэтому для развёрнутого приложения этот путь отличается. IFileProvider программное обеспечение, которое я написал, берет IFileProvider из startup.cs и тогда я мог бы просто использовать GetFileInfo() как я бы использовал MapPath в прошлом.

Ответ 4

Благодаря @NKosi, но IHostingEnvironment устарел в ядре MVC 3 !!

в соответствии с этим:

Устаревшие типы (предупреждение):

Microsoft.Extensions.Hosting.IHostingEnvironment
Microsoft.AspNetCore.Hosting.IHostingEnvironment
Microsoft.Extensions.Hosting.IApplicationLifetime
Microsoft.AspNetCore.Hosting.IApplicationLifetime
Microsoft.Extensions.Hosting.EnvironmentName
Microsoft.AspNetCore.Hosting.EnvironmentName

Новые типы:

Microsoft.Extensions.Hosting.IHostEnvironment
Microsoft.AspNetCore.Hosting.IWebHostEnvironment : IHostEnvironment
Microsoft.Extensions.Hosting.IHostApplicationLifetime
Microsoft.Extensions.Hosting.Environments 

Поэтому вы должны использовать IWebHostEnvironment вместо IHostingEnvironment.

public class HomeController : Controller
{
    private readonly IWebHostEnvironment _webHostEnvironment;

    public HomeController(IWebHostEnvironment webHostEnvironment)
    {
        _webHostEnvironment= webHostEnvironment;
    }

    public IActionResult Index()
    {
        string webRootPath = _webHostEnvironment.WebRootPath;
        string contentRootPath = _webHostEnvironment.ContentRootPath;

        return Content(webRootPath + "\n" + contentRootPath);
    }
}

Ответ 5

.NET Core 3.0

Вариант 1:

string path = System.IO.Directory.GetCurrentDirectory();

Вар 2:

string path = AppDomain.CurrentDomain.BaseDirectory.Substring(0, AppDomain.CurrentDomain.BaseDirectory.IndexOf("\\bin"));