Як отримати кореневий каталог проекту в ядрі asp.net. Directory.GetCurrentDirectory (), здається, не працює коректно на mac


83

Мій проект має структуру папок на мелодії:

  • Проект,
  • Проект / дані
  • Проект / двигун
  • Проект / Сервер
  • проект / фронт-енд

На сервері (що працює в папці 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 або налагодження). Але коли я запустив його на Mac, він " Directory.GetCurrentDirectory()" надіслав мене до / usr // [щось інше]. Це не стосувалося папки, де лежить мій проект.

Який правильний спосіб знайти відносні шляхи в моєму проекті? Де я повинен зберігати папку даних таким чином, щоб вона була легко доступною для всіх підпроектів у рішенні - зокрема, для проекту сервера kestrel? Я вважаю за краще не зберігати його в папці wwwroot, оскільки папка даних підтримується іншим членом команди, і я просто хочу отримати доступ до останньої версії. Які у мене варіанти?

Відповіді:


74

Залежно від того, де ви перебуваєте в трубопроводі пустелі - якщо у вас є доступ до IConfiguration( Startup.csконструктор ) або IWebHostEnvironment( ранішеIHostingEnvironment ), ви можете або ввести IWebHostEnvironmentфайл у свій конструктор, або просто запитати ключ у конфігурації.

Вводити IWebHostEnvironmentв Startup.csконструктор

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

Використання IConfiguration у конструкторі Startup.cs

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

можливо, ви можете ввести IConfiguration у контролер і отримати від цього те, що вам потрібно. так?
Єгуда Макаров

1
як ми можемо отримати доступ до contentRoot під час запуску?
Cihan Küsmez

3
IHostingEnvironment тепер застарілий в Core, і його замінив IWebHostEnvironment
Антоніо Родрігес,

1
@ AntonioRodríguez - оновлений для відображення, IWebHostEnvironmentзнаряддя праці IHostEnvironment- посилання - IHostingEnvironmentскасовано
SliverNinja - MSFT

61

Зараз працює над .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

2
Цей підхід добре працював і для .Net Core 2.2
Магнус

1
оскільки хочете отримати шлях до файлу в режимі розробки, означає, що під час запуску проекту з візуальної студії "_hostingEnvironment.WebRootPath" та "hostingEnvironment.ContentRootPath" обидва повертає нуль. що мені робити, щоб отримати шлях до файлу
malik saifullah

@maliksaifullah переконайтесь, що ви wwwrootє там у проекті і що він не порожній.
StefanJM

@maliksaifullah Чи можете ви показати мені свій контролер, де ви намагаєтесь отримати шлях?
StefanJM

@maliksaifullah Ви реєструєте послугу в контролері? Я не думаю, що IHostingEvironmentтут вводять ін’єкцію залежностей, і в цьому проблема.
StefanJM

21

У деяких випадках _hostingEnvironment.ContentRootPathі System.IO.Directory.GetCurrentDirectory()цілях в вихідний каталог. Ось помилка про це.

Запропоноване там рішення мені допомогло

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

Усі програми .NET Core - це консолі.
harveyt

У додатку Core це повернуло "... \ bin \ Debug \ netcoreapp \", а не кореневу папку проекту, як очікувалося.
Роберто

Папку проекту @Roberto Root для мережевих основних програм не слід повертати. Це правильна поведінка.
алеха

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 на 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 проти поточного каталогу та @CodeNotFound (яку було відкликано, оскільки вона не спрацювала через вищезазначену помилку), яку в основному можна знайти тут: Отримання шляху WebRoot та кореневого шляху вмісту в Asp.net Ядро


7
FYI, якщо вам цікаво, як отримати IHostingEnvironment у класі запуску: додайте його як аргумент конструктора.
Endy Tjahjono

16

Спробуйте заглянути тут: Найкращий спосіб отримати шлях до папки програми

Цитата звідти:

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


15

Якщо ви використовуєте 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

1

Якщо це може бути корисно комусь, у файлі 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... який безлад!


0

Здається, IHostingEnvironment замінено на IHostEnvironment (і кілька інших). Ви повинні мати можливість змінити тип інтерфейсу у своєму коді, і все буде працювати як раніше :-)

Ви можете знайти більше інформації про зміни за цим посиланням на GitHub https://github.com/aspnet/AspNetCore/issues/7749

EDIT Існує також додатковий інтерфейс IWebHostEnvironment, який можна використовувати в програмах ASP.NET Core. Це доступно у просторі імен Microsoft.AspNetCore.Hosting.

Посилання: https://stackoverflow.com/a/55602187/932448

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.