如何在 asp.net core 中获取项目的根目录。 Directory.GetCurrentDirectory() 在 Mac 上似乎无法正常工作

Posted

技术标签:

【中文标题】如何在 asp.net core 中获取项目的根目录。 Directory.GetCurrentDirectory() 在 Mac 上似乎无法正常工作【英文标题】:How to get root directory of project in asp.net core. Directory.GetCurrentDirectory() doesn't seem to work correctly on a 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 文件夹中,因为数据文件夹由团队中的其他成员维护,我只想访问最新版本。我有哪些选择?

【问题讨论】:

【参考方案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://***.com/a/55602187/932448

【讨论】:

这是另一个答案的文字复制和粘贴。您应该将问题标记为重复,而不是复制内容。

以上是关于如何在 asp.net core 中获取项目的根目录。 Directory.GetCurrentDirectory() 在 Mac 上似乎无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

[Asp.Net Core]Asp.Net Core与配置系统的集成

[Asp.Net Core]Asp.Net Core与配置系统的集成

[Asp.Net Core]Asp.Net Core与配置系统的集成

第二十九节: Asp.Net Core零散总结(各种目录内外网ip)[不断补充]

Asp.Net Core 中的静态文件

ASP.Net Core:如何获取无效 ModelState 值的键?