繁体   English   中英

如何在 asp.net 内核中获取项目的根目录。 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

我的项目具有以下文件夹结构:

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

在服务器(在 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 管道中的位置 - 如果您有权访问IConfigurationStartup.cs构造函数)或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);
}

目前在 .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.ContentRootPathSystem.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: IHostEnvironmentMicrosoft.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 命名空间中可用。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM