如何获取 asp.net 核心目录中的项目根目录。 GetCurrentDirectory()似乎不能在 Mac 上正常工作

我的项目的文件夹结构如下:

  • 工程项目,
  • 工程项目/资料
  • 工程项目/引擎
  • 项目/服务器
  • 项目/前端

In the server (running in the Project/Server folder) I refer to the folder like this:

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 或调试文件夹)。 但是当我在 Mac 上运行它时,它被“ Directory.GetCurrentDirectory()”发送到/usr//[ something else ]。它没有引用我的项目所在的文件夹。

What is the correct way to find relative paths in my project? Where should I store the data folder in a way that it is easily accessible to all the sub projects in the solution - specifically to the kestrel server project? I prefer to not have to store it in the wwwroot folder because the data folder is maintained by a different member in the team, and I just want to access the latest version. What are my options?

244923 次浏览

看这里: 获取应用程序文件夹路径的最佳方法

引用下面的话:

System.IO.Directory.GetCurrentDirectory()返回当前 directory, which may or may not be the folder where the application is 定位。环境。当前目录也是如此 如果在 DLL 文件中使用它,它将返回 进程正在运行(在 ASP.NET 中尤其如此)。

如前所述(并收回)。若要获取 基地目录(如正在运行的程序集的位置) ,请不要使用 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"));

I realised my mistake by reading BaseDirectory 与工作目录 and @CodeNotFound founds answer (which was retracted because it didn't work because of the above mistake) which basically can be found here: 在 Asp.net 内核中获取 WebRoot 路径和内容根路径

取决于你在哪里的 kestrel 管道-如果你有访问 IConfiguration(Startup.cs constructor)或 IWebHostEnvironment(前身为 IHostingEnvironment) ,你可以注入 IWebHostEnvironment到你的构造函数或只是请求配置的关键。

Startup.cs构造函数中注入 IWebHostEnvironment

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

在 Startup.cs 构造函数中使用 IConfiguration

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

In some cases _hostingEnvironment.ContentRootPath and System.IO.Directory.GetCurrentDirectory() targets to source directory. Here is 臭虫 about it.

The solution proposed there helped me

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

目前正在处理.Net Core 2.2和3.0。

获取 Controller:中的项目根目录

  • 为宿主环境创建属性

    private readonly IHostingEnvironment _hostingEnvironment;
    
  • Add Microsoft.AspNetCore.Hosting to your controller

    using Microsoft.AspNetCore.Hosting;
    
  • Register the service in the constructor

    public HomeController(IHostingEnvironment hostingEnvironment) {
    _hostingEnvironment = hostingEnvironment;
    }
    
  • Now, to get the projects root path

    string projectRootPath = _hostingEnvironment.ContentRootPath;
    

To get the "wwwroot" path, use

_hostingEnvironment.WebRootPath

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

using System.IO;


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

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

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

似乎 IHostingEnvironment 已经被 IHostEnvironment 取代了 (以及其他一些) 您的代码和一切都将像以前一样工作: -)

您可以在 GitHub 的这个链接上找到更多关于更改的信息 Https://github.com/aspnet/aspnetcore/issues/7749

还有一个附加的接口 IWebHostEnvironment 可以在 ASP.NET 核心应用程序中使用 托管名称空间。

档号: https://stackoverflow.com/a/55602187/932448

如果这对任何人都有用,那么在 Razor Page 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中... ... 真是一团糟!

如果通过 DI 使用 IWebHostEnvironment不是您的选择,请使用

AppContext.BaseDirectory

基于 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);
}

我测试和比较 asp.net 核心6,我认为这可以帮助某人。

假设您的项目位置路径是 D:\Project\Server,如果您使用 linux 或 mac,只需将 \替换为 /

var app = builder.Build();
IWebHostEnvironment environment = app.Configuration.Environment;


System.Console.WriteLine(environment.ContentRootPath);
// D:\Project\Server\
System.Console.WriteLine(environment.WebRootPath);
// D:\Project\Server\wwwroot


System.Console.WriteLine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
// D:\Project\Server\bin\Debug\net6.0
System.Console.WriteLine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase));
// file:\D:\Project\Server\bin\Debug\net6.0
System.Console.WriteLine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));
// D:\Project\Server\bin\Debug\net6.0


System.Console.WriteLine(Directory.GetCurrentDirectory());
// D:\Project\Server
System.Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
// D:\Project\Server\bin\Debug\net6.0\
System.Console.WriteLine(AppContext.BaseDirectory);
// D:\Project\Server\bin\Debug\net6.0\

注意: 如果 environment.WebRootPath是空字符串,您需要在根项目中创建 wwwroot文件夹,然后一切工作正常。