How to get absolute path in ASP.Net Core alternati

2020-01-30 08:32发布

How to get absolute path in ASP net core alternative way for Server.MapPath

I have tried to use IHostingEnvironment but it doesn't give proper result.

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

I have one image file (Sample.PNG) in wwwroot folder I need to get this absolute path.

5条回答
趁早两清
2楼-- · 2020-01-30 08:50

* Hack * Not recommended, but FYI you can get an absolute path from a relative path with var abs = Path.GetFullPath("~/Content/Images/Sample.PNG").Replace("~\\","");

Prefer the DI/Service approaches above, but if you are in a non-DI situation (e.g., a class instantiated with Activator) this will work.

查看更多
对你真心纯属浪费
3楼-- · 2020-01-30 08:51

Update

As of .Net Core v3.0, it should be IWebHostEnvironment instead of IHostingEnvironment as the WebRootPath has been moved to the web specific environment interface.

public class HomeController : Controller {
    private IWebHostEnvironment _hostingEnvironment;

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

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

Original Answer

Inject IHostingEnvironment as a dependency into the dependent class. The framework will populate it for you

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

You could go one step further and create your own path provider service abstraction and implementation.

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

And inject IPathProvider into dependent classes.

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

Make sure to register the service with the DI container

services.AddSingleton<IPathProvider, PathProvider>();
查看更多
来,给爷笑一个
4楼-- · 2020-01-30 08:51

.NET Core 3.0

Var 1:

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

Var 2:

string path = AppDomain.CurrentDomain.BaseDirectory.Substring(0, AppDomain.CurrentDomain.BaseDirectory.IndexOf("\\bin"));
查看更多
手持菜刀,她持情操
5楼-- · 2020-01-30 08:57

A better solution is to use the IFileProvider.GetFileInfo() method.

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

You must register IFileProvider like this to be able to access it through 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);
    }

As you can see this logic (for where a file comes from) can get quite complex, but your code won't break if it changes.

You can create a custom IFileProvider with new PhysicalFileProvider(root) if you have some special logic. I had a situation where I want to load an image in middleware, and resize or crop it. But it's an Angular project so the path is different for a deployed app. The middleware I wrote takes IFileProvider from startup.cs and then I could just use GetFileInfo() like I would have used MapPath in the past.

查看更多
【Aperson】
6楼-- · 2020-01-30 09:07

Thanks to @NKosi but IHostingEnvironment is obsoleted in MVC core 3!!

according to this :

Obsolete types (warning):

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

New types:

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

So you must use IWebHostEnvironment instead of 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);
    }
}
查看更多
登录 后发表回答