【问题标题】:How to get absolute path in ASP.Net Core alternative way for Server.MapPath如何在 ASP.Net Core 替代方式中获取 Server.MapPath 的绝对路径
【发布时间】:2017-10-14 23:48:59
【问题描述】:

如何在 Server.MapPath

的 ASP 网络核心替代方式中获取绝对路径

我尝试使用 IHostingEnvironment,但没有给出正确的结果。

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

我在 wwwroot 文件夹中有一个图像文件 (Sample.PNG),我需要获取此绝对路径。

【问题讨论】:

  • 将其作为依赖注入到依赖类中。框架将为您填充它。
  • 如果我们在 Owin 管道之外手动创建自己的类,有没有办法注入 IHostingEnvironment 依赖项?

标签: c# asp.net asp.net-core .net-core asp.net-core-mvc


【解决方案1】:

从.Net Core v3.0 开始,访问WebRootPath 应该是IWebHostEnvironment,该WebRootPath 已移至Web 特定环境接口。

IWebHostEnvironment 作为依赖注入到依赖类中。该框架将为您填充它

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

您可以更进一步,创建自己的路径提供者服务抽象和实现。

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

并将IPathProvider 注入依赖类。

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

确保向 DI 容器注册服务

services.AddSingleton<IPathProvider, PathProvider>();

【讨论】:

    【解决方案2】:

    .Net Core 3

    例如我要定位~/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();
        }
    }
    

    一些技巧

    此外,如果您没有控制器或服务,请按照最后一部分并将其类注册为单例。 然后,在 Startup.ConfigureServices 中:

    services.AddSingleton<your_class_Name>();
    

    最后,在你需要的地方注入your_class_Name


    .Net Core 2

    例如我要定位~/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();
        }
    }
    

    更多详情

    感谢@NKosi,但 IHostingEnvironment 在 MVC 核心 3 中已过时!!

    根据this

    过时类型(警告):

    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

    【讨论】:

      【解决方案3】:

      .NET Core 3.0

      变量 1:

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

      变量 2:

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

      【讨论】:

        【解决方案4】:

        * 破解 * 不推荐,但仅供参考,您可以从相对路径中获取绝对路径 var abs = Path.GetFullPath("~/Content/Images/Sample.PNG").Replace("~\\","");

        更喜欢上面的 DI/Service 方法,但如果您处于非 DI 情况(例如,使用 Activator 实例化的类),这将起作用。

        【讨论】:

        • 感谢您添加此内容。我需要从静态类中的静态方法将一些数据保存到文件(用户无法访问)到我的 asp.net 核心应用程序,这救了我。
        • 我有一个反射场景(激活器),所以这节省了我的时间。谢谢
        【解决方案5】:

        更好的解决方案是使用IFileProvider.GetFileInfo() 方法。

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

        你必须注册IFileProviderlike 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);
            }
        

        正如您所见,这个逻辑(文件来自何处)可能会变得相当复杂,但如果它发生变化,您的代码不会中断。

        如果您有一些特殊的逻辑,您可以使用new PhysicalFileProvider(root) 创建自定义IFileProvider。我有一种情况,我想在中间件中加载图像,然后调整大小或裁剪它。但它是一个 Angular 项目,所以部署的应用程序的路径是不同的。我编写的中间件从startup.cs 中获取IFileProvider,然后我可以像过去使用MapPath 一样使用GetFileInfo()

        【讨论】:

        • _hostingEnvironment 未定义。它来自哪里?
        • 为了完整起见,@JimS,如果您有该类型的构造函数参数,则框架会注入 IHostingEnvironment。 _hostingEnvironment 是控制器类中设置为 IHostingEnvironment 的字段
        • 感谢您添加。我想我错过了,但你可以在 Nkosi 的回答中看到它。
        猜你喜欢
        • 1970-01-01
        • 2013-07-13
        • 2022-12-06
        • 1970-01-01
        • 2011-01-21
        • 2015-05-05
        • 2017-03-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多