【问题标题】:How to get root directory of project in asp.net core. Directory.GetCurrentDirectory() doesn't seem to work correctly on a mac如何在 asp.net core 中获取项目的根目录。 Directory.GetCurrentDirectory() 在 Mac 上似乎无法正常工作
【发布时间】:2017-09-28 07:27:39
【问题描述】:

我的项目有一个文件夹结构:

  • 项目,
  • 项目/数据
  • 项目/引擎
  • 项目/服务器
  • 项目/前端

在服务器中(在 Project/Server 文件夹中运行)我指的是这样的文件夹:

var rootFolder = Directory.GetCurrentDirectory();
rootFolder = rootFolder.Substring(0,
            rootFolder.IndexOf(@"\Project\", StringComparison.Ordinal) + @"\Project\".Length);
PathToData = Path.GetFullPath(Path.Combine(rootFolder, "Data"));

var Parser = Parser();
var d = new FileStream(Path.Combine(PathToData, $"{dataFileName}.txt"), FileMode.Open);
var fs = new StreamReader(d, Encoding.UTF8);

在我的 Windows 机器上,这段代码运行良好,因为 Directory.GetCurrentDirectory() 引用了当前文件夹,并且正在做

rootFolder.Substring(0, rootFolder.IndexOf(@"\Project\", StringComparison.Ordinal) + @"\Project\".Length); 

获取项目的根文件夹(不是 bin 或 debug 文件夹)。 但是当我在 Mac 上运行它时,它得到“Directory.GetCurrentDirectory()”将我发送到 /usr//[其他东西]。它没有引用我的项目所在的文件夹。

在我的项目中查找相对路径的正确方法是什么?我应该在哪里存储数据文件夹,以便解决方案中的所有子项目都可以轻松访问 - 特别是红隼服务器项目?我宁愿不必将其存储在 wwwroot 文件夹中,因为数据文件夹由团队中的其他成员维护,我只想访问最新版本。我有哪些选择?

【问题讨论】:

    标签: c# asp.net-core


    【解决方案1】:

    取决于您在红隼管道中的位置 - 如果您有权访问 IConfigurationStartup.cs 构造函数)或 IWebHostEnvironment以前为 IHostingEnvironment ) 您可以将IWebHostEnvironment 注入到您的构造函数中,也可以只从配置中请求密钥。

    Startup.cs构造函数中注入IWebHostEnvironment

    public Startup(IConfiguration configuration, IWebHostEnvironment env)
    {
         var contentRoot = env.ContentRootPath;
    }
    

    Using IConfiguration in Startup.cs Constructor

    public Startup(IConfiguration configuration)
    {
         var contentRoot = configuration.GetValue<string>(WebHostDefaults.ContentRootKey);
    }
    

    【讨论】:

    • 您可能可以将 IConfiguration 注入控制器,并从中获取您需要的内容。对吗?
    • 我们如何在 Startup 中访问 c​​ontentRoot ?
    • IHostingEnvironment 现在已过时 int Core ,并由 IWebHostEnvironment 取代
    • @AntonioRodríguez - 更新以反映,IWebHostEnvironment 实现 IHostEnvironment - reference - IHostingEnvironment has been retired
    【解决方案2】:

    目前正在开发 .Net Core 2.2 和 3.0。

    控制器中获取项目根目录:

    • 为宿主环境创建一个属性

      private readonly IHostingEnvironment _hostingEnvironment;
      
    • 将 Microsoft.AspNetCore.Hosting 添加到您的控制器

      using Microsoft.AspNetCore.Hosting;
      
    • 在构造函数中注册服务

      public HomeController(IHostingEnvironment hostingEnvironment) {
          _hostingEnvironment = hostingEnvironment;
      }
      
    • 现在,获取项目根路径

      string projectRootPath = _hostingEnvironment.ContentRootPath;
      

    要获取“wwwroot”路径,请使用

    _hostingEnvironment.WebRootPath
    

    【讨论】:

    • 这种方法也适用于 .Net Core 2.2
    • 因为想要在开发模式下获取文件路径意味着从 Visual Studio 运行项目时“_hostingEnvironment.WebRootPath”和“hostingEnvironment.ContentRootPath”都返回空值。我应该怎么做才能得到文件路径
    • @maliksaifullah 检查您的wwwroot 是否在项目中并且它不为空。
    • @maliksaifullah 你能告诉我你的控制器你想在哪里找到路径吗?
    • @maliksaifullah 您是否在控制器中注册服务?我不认为IHostingEvironment 是在这里使用依赖注入注入的,这就是问题所在。
    【解决方案3】:

    在某些情况下,_hostingEnvironment.ContentRootPathSystem.IO.Directory.GetCurrentDirectory() 以源目录为目标。这是bug 关于它。

    那里提出的解决方案帮助了我

    Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
    

    【讨论】:

    • 所有 .NET Core 应用程序都是一个控制台。
    • 在核心应用程序中,这返回了“...\bin\Debug\netcoreapp\”,而不是预期的根项目文件夹。
    • @Roberto Root 网络核心应用程序的项目文件夹不应返回。这是正确的行为。
    【解决方案4】:

    如前所述(并撤回)。要获取 base 目录,就像在运行程序集的位置一样,不要使用 Directory.GetCurrentDirectory(),而是从 IHostingEnvironment.ContentRootPath 获取它。

    private IHostingEnvironment _hostingEnvironment;
        private string projectRootFolder;
        public Program(IHostingEnvironment env)
        {
            _hostingEnvironment = env;
            projectRootFolder = env.ContentRootPath.Substring(0,
                env.ContentRootPath.LastIndexOf(@"\ProjectRoot\", StringComparison.Ordinal) + @"\ProjectRoot\".Length);
        }
    

    但是我犯了一个额外的错误:我在启动时将 ContentRoot 目录设置为 Directory.GetCurrentDirectory() 破坏了我想要的默认值! 在这里我注释掉了有问题的行:

     public static void Main(string[] args)
        {
            var host = new WebHostBuilder().UseKestrel()
               // .UseContentRoot(Directory.GetCurrentDirectory()) //<== The mistake
                .UseIISIntegration()
                .UseStartup<Program>()
                .Build();
            host.Run();
        }
    

    现在它运行正常 - 我现在可以导航到我的项目根目录的子文件夹:

    var pathToData = Path.GetFullPath(Path.Combine(projectRootFolder, "data"));
    

    我通过阅读BaseDirectory vs. Current Directory 和@CodeNotFound 发现了我的错误(由于上述错误而被撤回,因为它没有工作)基本上可以在这里找到:Getting WebRoot Path and Content Root Path in Asp.net Core

    【讨论】:

    • 仅供参考,如果您想知道如何在 Startup 类中获取 IHostingEnvironment:将其添加为构造函数参数。
    【解决方案5】:

    试试看这里:Best way to get application folder path

    从那里引用:

    System.IO.Directory.GetCurrentDirectory() 返回当前 目录,可能是也可能不是应用程序所在的文件夹 位于。 Environment.CurrentDirectory 也是如此。万一你 在 DLL 文件中使用它,它将返回 进程正在运行(在 ASP.NET 中尤其如此)。

    【讨论】:

      【解决方案6】:

      如果您使用的是 ASP.NET MVC Core 3 或更新版本,IHostingEnvironment 已被弃用并替换为 IWebHostEnvironment

      public Startup(IWebHostEnvironment webHostEnvironment)
      {
          var webRootPath = webHostEnvironment.WebRootPath;
      }
      

      【讨论】:

      • 从技术上讲,我相信IHostingEnvironment 已被IHostEnvironment 取代。 IWebHostEnvironment 是一个更具体的变体,特定于网络主机。库项目(甚至可以说是您自己的解决方案的类库)可能会很好地避免对 IWebHostEnvironment 的依赖,因为它们不能保证它们将在 web 主机中运行。
      【解决方案7】:

      我用这段代码解决了这个问题:

      using System.IO;
      
      var path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location.Substring(0, Assembly.GetEntryAssembly().Location.IndexOf("bin\\")))
      

      【讨论】:

      • 一个实际上可以理解且有效的答案。谢谢!
      • 请不要使用这个答案,因为它硬编码了bin,可能不存在!
      【解决方案8】:

      如果这对任何人都有用,在 Razor 页面 cshtml.cs 文件中,获取方法如下:向构造函数添加 IHostEnvironment hostEnvironment 参数,它将自动注入:

      public class IndexModel : PageModel
      {
          private readonly ILogger<IndexModel> _logger;
          private readonly IHostEnvironment _hostEnvironment;
      
          public IndexModel(ILogger<IndexModel> logger, IHostEnvironment hostEnvironment)
          {
              _logger = logger;
              _hostEnvironment = hostEnvironment; // has ContentRootPath property
          }
      
          public void OnGet()
          {
      
          }
      }
      

      PS:IHostEnvironmentMicrosoft.Extensions.Hosting 命名空间中,在 Microsoft.Extensions.Hosting.Abstractions.dll ... 真是一团糟!

      【讨论】:

        【解决方案9】:

        如果您不适合通过 DI 使用 IWebHostEnvironment,请使用

        AppContext.BaseDirectory
        

        【讨论】:

        • 不确定为什么两个选项给出不同的值。我寻找的正确的是 BaseDirectory。谢谢!
        【解决方案10】:

        基于 Henrique A 技术并支持单元测试上下文...

        ReadOnlySpan<char> appPath = Assembly.GetEntryAssembly().Location.Replace("YOURTestProject", "YOUR");
        var dir = Path.GetDirectoryName(appPath.Slice(0, appPath.IndexOf("bin\\")));
        string path = Path.Combine(dir.ToString(), "Resources", "countries.dat");
        if (System.IO.File.Exists(path))
        {
            countries = System.IO.File.ReadAllLines(path);
        }
        

        【讨论】:

          【解决方案11】:

          似乎 IHostingEnvironment 已被 IHostEnvironment 取代 (和其他一些人)。您应该能够更改接口类型 你的代码和一切都会像以前一样工作:-)

          您可以在 GitHub 上的此链接中找到有关更改的更多信息 https://github.com/aspnet/AspNetCore/issues/7749

          EDIT 还有一个额外的接口 IWebHostEnvironment 可用于 ASP.NET Core 应用程序。这可在 Microsoft.AspNetCore.Hosting 命名空间。

          参考:https://stackoverflow.com/a/55602187/932448

          【讨论】:

          • 这是另一个答案的文字复制和粘贴。您应该将问题标记为重复,而不是复制内容。
          猜你喜欢
          • 1970-01-01
          • 2019-06-24
          • 1970-01-01
          • 2013-09-24
          • 1970-01-01
          • 1970-01-01
          • 2023-03-11
          • 1970-01-01
          相关资源
          最近更新 更多