So erhalten Sie das Stammverzeichnis des Projekts im asp.net-Kern. Directory.GetCurrentDirectory () scheint auf einem Mac nicht richtig zu funktionieren

78

Mein Projekt hat eine Ordnerstruktur wie folgt:

  • Projekt,
  • Projekt / Daten
  • Projekt / Motor
  • Projekt / Server
  • Projekt / Frontend

Auf dem Server (der im Ordner Projekt / Server ausgeführt wird) verweise ich auf den Ordner wie folgt:

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);

Auf meinem Windows-Computer funktioniert dieser Code Directory.GetCurrentDirectory()einwandfrei, da er auf den aktuellen Ordner übertragen wurde

rootFolder.Substring(0, rootFolder.IndexOf(@"\Project\", StringComparison.Ordinal) + @"\Project\".Length); 

holt mir den Stammordner des Projekts (nicht die Ordner bin oder debug). Aber als ich es auf einem Mac laufen ließ, wurde es " Directory.GetCurrentDirectory()" an / usr // [etwas anderes] gesendet. Es bezog sich nicht auf den Ordner, in dem mein Projekt liegt.

Was ist der richtige Weg, um relative Pfade in meinem Projekt zu finden? Wo soll ich den Datenordner so speichern, dass er für alle Unterprojekte in der Lösung leicht zugänglich ist - speziell für das Turmfalken-Server-Projekt? Ich möchte es lieber nicht im Ordner wwwroot speichern müssen, da der Datenordner von einem anderen Mitglied im Team verwaltet wird und ich nur auf die neueste Version zugreifen möchte. Was sind meine Optionen?

Akraines
quelle

Antworten:

68

Je nachdem, wo Sie sich in der Turmfalken-Pipeline befinden - wenn Sie Zugriff auf IConfiguration( Startup.csKonstruktor ) oder IWebHostEnvironment( früherIHostingEnvironment ) haben, können Sie diese entweder IWebHostEnvironmentin Ihren Konstruktor einfügen oder einfach den Schlüssel von der Konfiguration anfordern.

IWebHostEnvironmentIn den Startup.csKonstruktor injizieren

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

Verwenden der IConfiguration im Startup.cs-Konstruktor

public Startup(IConfiguration configuration)
{
     var contentRoot = configuration.GetValue<string>(WebHostDefaults.ContentRootKey);
}
SliverNinja - MSFT
quelle
Sie können wahrscheinlich IConfiguration in den Controller einspeisen und das bekommen, was Sie brauchen. richtig?
Yehuda Makarov
1
Wie können wir im Startup auf contentRoot zugreifen?
Cihan Küsmez
3
IHostingEnvironment ist jetzt in Core veraltet und wird durch IWebHostEnvironment
Antonio Rodríguez
1
@ AntonioRodríguez - aktualisiert, um zu reflektieren, IWebHostEnvironmentimplementiert IHostEnvironment- Referenz - IHostingEnvironmentwurde zurückgezogen
SliverNinja - MSFT
61

Ab sofort wird an .Net Core 2.2 und 3.0 gearbeitet.

So rufen Sie das Projektstammverzeichnis in einem Controller ab:

  • Erstellen Sie eine Eigenschaft für die Hosting-Umgebung

    private readonly IHostingEnvironment _hostingEnvironment;
    
  • Fügen Sie Ihrem Controller Microsoft.AspNetCore.Hosting hinzu

    using Microsoft.AspNetCore.Hosting;
    
  • Registrieren Sie den Service im Konstruktor

    public HomeController(IHostingEnvironment hostingEnvironment) {
        _hostingEnvironment = hostingEnvironment;
    }
    
  • Nun, um den Stammpfad des Projekts zu erhalten

    string projectRootPath = _hostingEnvironment.ContentRootPath;
    

Verwenden Sie , um den Pfad " wwwroot " abzurufen

_hostingEnvironment.WebRootPath
StefanJM
quelle
2
Dies näherte sich gut für .Net Core 2.2
Magnus Wallström
1
Wenn Sie den Dateipfad im Entwicklungsmodus erhalten möchten, geben Sie beim Ausführen des Projekts von Visual Studio "_hostingEnvironment.WebRootPath" und "HostingEnvironment.ContentRootPath" beide die Null zurück. Was soll ich tun, um den Dateipfad zu erhalten
Malik Saifullah
@maliksaifullah Überprüfen Sie, ob Sie wwwrootim Projekt vorhanden sind und ob es nicht leer ist.
StefanJM
@maliksaifullah Kannst du mir deinen Controller zeigen, wo du den Weg finden willst?
StefanJM
@maliksaifullah Registrieren Sie den Dienst im Controller? Ich glaube nicht, dass das IHostingEvironmenthier mit Abhängigkeitsinjektion injiziert wird, und das ist das Problem.
StefanJM
21

In einigen Fällen _hostingEnvironment.ContentRootPathund System.IO.Directory.GetCurrentDirectory()Ziele zum Quellverzeichnis. Hier ist ein Fehler .

Die dort vorgeschlagene Lösung hat mir geholfen

Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
aleha
quelle
Alle .NET Core-Anwendungen sind Konsolen.
Harvey
In einer Core-App gab dies "... \ bin \ Debug \ netcoreapp \" und nicht wie erwartet den Stammprojektordner zurück.
Roberto
Der @ Roberto Root-Projektordner für Net Core-Apps sollte nicht zurückgegeben werden. Dies ist ein korrektes Verhalten.
Aleha
20

Wie zuvor beantwortet (und zurückgezogen). Verwenden Sie Directory.GetCurrentDirectory () nicht, um das Basisverzeichnis wie am Speicherort der ausgeführten Assembly abzurufen, sondern beziehen Sie es von 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);
    }

Ich habe jedoch einen zusätzlichen Fehler gemacht: Ich hatte das ContentRoot-Verzeichnis beim Start auf Directory.GetCurrentDirectory () gesetzt, wodurch der von mir gewünschte Standardwert untergraben wurde! Hier habe ich die beleidigende Zeile auskommentiert:

 public static void Main(string[] args)
    {
        var host = new WebHostBuilder().UseKestrel()
           // .UseContentRoot(Directory.GetCurrentDirectory()) //<== The mistake
            .UseIISIntegration()
            .UseStartup<Program>()
            .Build();
        host.Run();
    }

Jetzt läuft es richtig - ich kann jetzt zu Unterordnern meines Projektstamms navigieren mit:

var pathToData = Path.GetFullPath(Path.Combine(projectRootFolder, "data"));

Ich habe meinen Fehler erkannt, indem ich BaseDirectory vs. Current Directory gelesen habe und @CodeNotFound die Antwort gefunden hat (die zurückgezogen wurde, weil sie aufgrund des obigen Fehlers nicht funktioniert hat), die im Grunde hier zu finden ist: Abrufen des WebRoot-Pfads und des Inhaltsstammpfads in Asp.net Ader

Akraines
quelle
7
Zu Ihrer Information, wenn Sie sich fragen, wie Sie IHostingEnvironment in der Startup-Klasse erhalten: Fügen Sie es als Konstruktorargument hinzu.
Endy Tjahjono
15

Versuchen Sie hier zu suchen: Der beste Weg, um den Pfad des Anwendungsordners zu erhalten

Um von dort zu zitieren:

System.IO.Directory.GetCurrentDirectory()Gibt das aktuelle Verzeichnis zurück, das möglicherweise der Ordner ist, in dem sich die Anwendung befindet. Gleiches gilt für Environment.CurrentDirectory. Wenn Sie dies in einer DLL-Datei verwenden, wird der Pfad zurückgegeben, in dem der Prozess ausgeführt wird (dies gilt insbesondere für ASP.NET).

shlgug
quelle
14

Wenn Sie ASP.NET MVC Core 3 oder höher verwenden, IHostingEnvironmentwurde es veraltet und durch ersetztIWebHostEnvironment

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

Ich habe das Problem mit diesem Code gelöst:

using System.IO;

var path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location.Substring(0, Assembly.GetEntryAssembly().Location.IndexOf("bin\\")))
Henrique A.
quelle
Eine Antwort, die eigentlich verständlich ist und funktioniert. Vielen Dank!
BMills
0

Es scheint, dass IHostingEnvironment durch IHostEnvironment (und einige andere) ersetzt wurde. Sie sollten in der Lage sein, den Schnittstellentyp in Ihrem Code zu ändern und alles wird so funktionieren, wie es früher war :-)

Weitere Informationen zu den Änderungen finden Sie unter diesem Link auf GitHub https://github.com/aspnet/AspNetCore/issues/7749

BEARBEITEN Es gibt auch eine zusätzliche Schnittstelle IWebHostEnvironment, die in ASP.NET Core-Anwendungen verwendet werden kann. Dies ist im Microsoft.AspNetCore.Hosting-Namespace verfügbar.

Ref: https://stackoverflow.com/a/55602187/932448

Ali Jamal
quelle
0

Wenn dies für jemanden in einer Razor Page-Datei cshtml.cs nützlich sein kann, gehen Sie wie folgt vor: Fügen Sie IHostEnvironment hostEnvironmentdem Konstruktor einen Parameter hinzu, der automatisch eingefügt wird:

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: IHostEnvironmentist im Microsoft.Extensions.HostingNamespace, in Microsoft.Extensions.Hosting.Abstractions.dll... was für ein Durcheinander!

Simon Mourier
quelle