How to get absolute path in ASP.Net Core alternative way for Server.MapPath

前端 未结 5 1570
野的像风
野的像风 2020-12-02 18:39

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

I have tried to use IHostingEnvironment

相关标签:
5条回答
  • 2020-12-02 18:43

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

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

    public class HomeController : Controller {
        private IWebHostEnvironment _hostEnvironment;
    
        public HomeController(IWebHostEnvironment environment) {
            _hostEnvironment = environment;
        }
    
        [HttpGet]
        public IActionResult Get() {
            string path = Path.Combine(_hostEnvironment.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 IWebHostEnvironment _hostEnvironment;
    
        public PathProvider(IWebHostEnvironment environment) {
            _hostEnvironment = environment;
        }
    
        public string MapPath(string path) {
            string filePath = Path.Combine(_hostEnvironment.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() {
            string path = pathProvider.MapPath("Sample.PNG");
            return View();
        }
    }
    

    Make sure to register the service with the DI container

    services.AddSingleton<IPathProvider, PathProvider>();
    
    0 讨论(0)
  • 2020-12-02 18:45

    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.

    0 讨论(0)
  • 2020-12-02 18:48

    .Net Core 3

    For example I want to locate ~/wwwroot/CSS

    public class YourController : Controller 
    {
        private readonly IWebHostEnvironment _webHostEnvironment;
    
        public YourController (IWebHostEnvironment webHostEnvironment)
        {
            _webHostEnvironment= webHostEnvironment;
        }
    
        public IActionResult Index()
        {
            string webRootPath = _webHostEnvironment.WebRootPath;
            string contentRootPath = _webHostEnvironment.ContentRootPath;
    
            string path ="";
            path = Path.Combine(webRootPath , "CSS");
            //or path = Path.Combine(contentRootPath , "wwwroot" ,"CSS" );
            return View();
        }
    }
    

    Some Tricks

    Also if you don't have a controller or service,follow last Part and register it's class as a singleton. Then, in Startup.ConfigureServices:

    services.AddSingleton<your_class_Name>();
    

    Finally, inject your_class_Name where you need it.


    .Net Core 2

    For example I want to locate ~/wwwroot/CSS

    public class YourController : Controller
    {
        private readonly IHostingEnvironment _HostEnvironment;
    
        public YourController (IHostingEnvironment HostEnvironment)
        {
            _HostEnvironment= HostEnvironment;
        }
    
        public ActionResult Index()
        {
            string webRootPath = _HostEnvironment.WebRootPath;
            string contentRootPath = _HostEnvironment.ContentRootPath;
    
            string path ="";
            path = Path.Combine(webRootPath , "CSS");
            //or path = Path.Combine(contentRootPath , "wwwroot" ,"CSS" );
            return View();
        }
    }
    

    MoreDetails

    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.

    0 讨论(0)
  • 2020-12-02 18:57

    .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"));
    
    0 讨论(0)
  • 2020-12-02 18:59

    * 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.

    0 讨论(0)
提交回复
热议问题