Как получить корневую директорию проекта в ядре asp.net. Directory.GetCurrentDirectory(), похоже, не работает правильно на mac

Мой проект имеет структуру папок:

  • Проект,
  • Проект/данные
  • Проект/Двигатель
  • Проект /Server
  • проект/передний конец

На сервере (работающем в папке 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//[something else]. Это не относится к папке, где находится мой проект.

Каков правильный способ поиска относительных путей в моем проекте? Где я должен хранить папку данных таким образом, чтобы она была легко доступна для всех подпроектов в решении - в частности, для проекта сервера kestrel? Я предпочитаю не хранить его в папке wwwroot, потому что папка данных поддерживается другим членом в команде, и я просто хочу получить доступ к последней версии. Какие у меня варианты?

Ответ 1

В зависимости от того, где вы находитесь в трубопроводе пустельги - если у вас есть доступ к IConfiguration (Startup.cs конструктор) или IHostingEnvironment вы можете либо вводить IHostingEnvironment в конструктор или просто запросить ключ от конфигурации.

Вводят IHostingEnvironment в Startup.cs Конструктора

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

Использование IConfiguration в Startup.cs Конструктор

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

Ответ 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

Ответ 3

Как ранее ответили (и убрали). Чтобы получить базовый каталог, как в расположении запущенной сборки, не используйте 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 нашел ответ (который был убран, потому что он не работал из-за вышеприведенная ошибка), которые в основном можно найти здесь: Получение пути и пути к корневому каталогу WebRoot в Core Asp.net

Ответ 4

В некоторых случаях _hostingEnvironment.ContentRootPath и System.IO.Directory.GetCurrentDirectory() ориентируются на исходный каталог. Вот ошибка об этом.

Предложенное там решение помогло мне

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

Ответ 5

Попробуйте найти здесь: Лучший способ получить путь к папке приложения

Процитировать оттуда:

System.IO.Directory.GetCurrentDirectory() возвращает текущий каталог, который может быть или не быть папкой, в которой приложение располагается. То же самое касается Environment.CurrentDirectory. Если вы используют это в DLL файле, он вернет путь, где процесс выполняется (это особенно верно в ASP.NET).

Ответ 6

Я решил проблему с этим кодом:

using System.IO;

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

Ответ 7

Если вы используете ASP.NET MVC Core 3 или новее, IHostingEnvironment устарела и заменена на IWebHostEnvironment

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