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


78

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

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

在服务器中(在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 // [其他]。它没有指向我的项目所在的文件夹。

在项目中查找相对路径的正确方法是什么?我应该将数据文件夹存储在解决方案中的所有子项目(特别是kestrel服务器项目)易于访问的地方吗?我宁愿不必将其存储在wwwroot文件夹中,因为数据文件夹是由团队中的其他成员维护的,而我只想访问最新版本。我有什么选择?

Answers:


68

根据您在kestrel管道中的位置-如果您可以访问IConfigurationStartup.cs构造函数)或IWebHostEnvironment以前IHostingEnvironment),则可以将注入IWebHostEnvironment到您的构造函数中,也可以只从配置中请求密钥。

注射IWebHostEnvironmentStartup.cs构造函数

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

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

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

您可能可以将IConfiguration注入到控制器中,并从中获得所需的东西。对?
Yehuda Makarov,

1
我们如何在Startup中访问contentRoot?
CihanKüsmez19年

3
IHostingEnvironment现在已过时int Core,由IWebHostEnvironment取代了
AntonioRodríguez

1
@AntonioRodríguez-已更新以反映,IWebHostEnvironment实施IHostEnvironment-参考-IHostingEnvironment已退休
SliverNinja-MSFT

61

到目前为止,在.Net Core 2.2和3.0上工作。

要在Controller中获取项目的根目录

  • 为托管环境创建属性

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

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

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

    string projectRootPath = _hostingEnvironment.ContentRootPath;
    

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

_hostingEnvironment.WebRootPath

2
这种方法对于.Net Core 2.2也很好用
MagnusWallström,

1
如要在开发模式下获取文件路径,则意味着从Visual Studio“ _hostingEnvironment.WebRootPath”和“ hostingEnvironment.ContentRootPath”运行项目时均返回null。我应该怎么做才能获得文件路径
malik saifullah 19-1-26

@maliksaifullah检查您wwwroot是否在项目中,并且它不为空。
StefanJM

@maliksaifullah您能告诉我您的控制器您试图获得路径的位置吗?
StefanJM

@maliksaifullah您是否正在控制器中注册服务?我不认为这里IHostingEvironment是使用依赖注入来注入的,这就是问题所在。
StefanJM

21

在某些情况下_hostingEnvironment.ContentRootPathSystem.IO.Directory.GetCurrentDirectory()目标是源目录。这是关于它的错误

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

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

所有.NET Core应用程序都是一个控制台。
哈维

在Core应用程序中,此操作返回“ ... \ bin \ Debug \ netcoreapp \”,而不是预期的根项目文件夹。
罗伯托

网络核心应用程序的@Roberto Root项目文件夹不应返回。这是正确的行为。
aleha

20

如先前的回答(并撤回)。要获取基本目录(如正在运行的程序集所在的位置),请不要使用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发现了我的错误(由于上述错误,它被撤消了,因为它不起作用),基本上可以在这里找到:在Asp.net中获取WebRoot路径和Content Root路径核心


7
仅供参考,如果您想知道如何在Startup类中获取IHostingEnvironment:将其添加为构造函数参数。
Endy Tjahjono,

15

尝试在此处查看:获取应用程序文件夹路径的最佳方法

从那里引用:

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


14

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

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

9

我用以下代码解决了问题:

using System.IO;

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

一个实际上可以理解并且可行的答案。谢谢!
BMills

0

看来IHostingEnvironment已被IHostEnvironment(和其他一些)取代。您应该能够在代码中更改接口类型,并且一切将按以前的方式工作:-)

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

编辑还有一个附加接口IWebHostEnvironment,可在ASP.NET Core应用程序中使用。在Microsoft.AspNetCore.Hosting命名空间中可用。

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


0

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.