[英]Directory.GetCurrentDirectory() doesn't point to bin folder anymore
[英]How to get root directory of project in asp.net core. Directory.GetCurrentDirectory() doesn't seem to work correctly on a mac
我的项目具有以下文件夹结构:
在服务器(在 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 文件夹中,因为数据文件夹由团队中的其他成员维护,我只想访问最新版本。 我有哪些选择?
根据您在 kestrel 管道中的位置 - 如果您有权访问IConfiguration
( Startup.cs
构造函数)或IWebHostEnvironment
(以前称为IHostingEnvironment
),您可以将IWebHostEnvironment
注入您的构造函数或仅从配置中请求密钥。
Startup.cs
构造函数中注入IWebHostEnvironment
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
var contentRoot = env.ContentRootPath;
}
public Startup(IConfiguration configuration)
{
var contentRoot = configuration.GetValue<string>(WebHostDefaults.ContentRootKey);
}
目前在 .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
在某些情况下_hostingEnvironment.ContentRootPath
和System.IO.Directory.GetCurrentDirectory()
目标到源目录。 这是关于它的错误。
那里提出的解决方案帮助了我
Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
如前所述(并撤回)。 要获取基本目录(如运行程序集的位置),请不要使用 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 设置为 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 founds 来意识到我的错误(由于上述错误而被撤回,因为它不起作用),基本上可以在这里找到: Getting WebRoot Path and Content Root Path in Asp.net核
试试看这里: Best way to get application folder path
从那里引用:
System.IO.Directory.GetCurrentDirectory()
返回当前目录,该目录可能是也可能不是应用程序所在的文件夹。 Environment.CurrentDirectory 也是如此。 如果您在 DLL 文件中使用它,它将返回进程运行的路径(这在 ASP.NET 中尤其如此)。
如果您使用的是 ASP.NET MVC Core 3 或更新版本, IHostingEnvironment
已被弃用并替换为IWebHostEnvironment
public Startup(IWebHostEnvironment webHostEnvironment)
{
var webRootPath = webHostEnvironment.WebRootPath;
}
我用这段代码解决了这个问题:
using System.IO;
var path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location.Substring(0, Assembly.GetEntryAssembly().Location.IndexOf("bin\\")))
如果这对任何人有用,在 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: IHostEnvironment
在Microsoft.Extensions.Hosting
命名空间中,在Microsoft.Extensions.Hosting.Abstractions.dll
…… IHostEnvironment
一团糟!
如果通过 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
文件夹,然后一切正常。
似乎 IHostingEnvironment 已被 IHostEnvironment(以及其他一些)取代。 您应该能够更改代码中的接口类型,一切都会像以前一样工作:-)
您可以在 GitHub https://github.com/aspnet/AspNetCore/issues/7749上的此链接中找到有关更改的更多信息
编辑 还有一个额外的接口 IWebHostEnvironment 可以在 ASP.NET Core 应用程序中使用。 这在 Microsoft.AspNetCore.Hosting 命名空间中可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.