web-dev-qa-db-fra.com

Comment obtenir le répertoire racine du projet dans le noyau asp.net. Directory.GetCurrentDirectory () ne semble pas fonctionner correctement sur un Mac

Mon projet a une structure de dossiers à la hauteur de:

  • Projet,
  • Projet/données
  • Projet/Moteur
  • Projet/serveur
  • projet/front-end

Sur le serveur (exécuté dans le dossier Projet/Serveur), je me réfère au dossier comme ceci:

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

Sur ma machine Windows, ce code fonctionne bien puisque Directory.GetCurrentDirectory() est renvoyé au dossier actuel et

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

me donne le dossier racine du projet (pas les dossiers bin ou debug). Mais quand je l'ai exécuté sur un mac, il a été envoyé par "Directory.GetCurrentDirectory()" à/usr // [quelque chose d'autre]. Cela ne faisait pas référence au dossier où se trouve mon projet.

Quelle est la bonne façon de trouver des chemins relatifs dans mon projet? Où devrais-je stocker le dossier de données de manière à ce qu'il soit facilement accessible à tous les sous-projets de la solution, en particulier au projet de serveur Kestrel? Je préfère ne pas avoir à le stocker dans le dossier wwwroot car le dossier de données est géré par un autre membre de l'équipe et je souhaite simplement accéder à la dernière version. Quelles sont mes options?

35
akraines

Selon votre position dans le pipeline Kestrel - si vous avez accès à IConfiguration (Startup.cs constructeur ) ou IHostingEnvironment vous pouvez soit injecter le IHostingEnvironment dans votre constructeur, soit simplement demander la clé à la configuration.

Injecter IHostingEnvironment dans Startup.cs Constructeur

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

tilisation de IConfiguration dans le constructeur Startup.cs

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

Travailler sur .Net Core 2.2 et 3.0 à partir de maintenant.

Pour obtenir le répertoire racine des projets dans un Controller:

  • Créer une propriété pour l'environnement d'hébergement

    private readonly IHostingEnvironment _hostingEnvironment;
    
  • Ajoutez Microsoft.AspNetCore.Hosting à votre contrôleur

    using Microsoft.AspNetCore.Hosting;
    
  • Enregistrer le service dans le constructeur

    public HomeController(IHostingEnvironment hostingEnvironment) {
        _hostingEnvironment = hostingEnvironment;
    }
    
  • Maintenant, pour obtenir le chemin racine des projets

    string projectRootPath = _hostingEnvironment.ContentRootPath;
    

Pour obtenir le chemin "wwwroot", utilisez

_hostingEnvironment.WebRootPath
34
StefanJM

Comme précédemment répondu (et rétracté). Pour obtenir le répertoire de base , comme dans l'emplacement de l'assembly en cours d'exécution, n'utilisez pas Directory.GetCurrentDirectory (), mais plutôt à partir de 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);
    }

Cependant, j'ai commis une erreur supplémentaire: j'avais défini le répertoire ContentRoot sur Directory.GetCurrentDirectory () au démarrage, ce qui nuisait à la valeur par défaut que j'avais tant souhaitée! Ici, j'ai commenté la ligne incriminée:

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

Maintenant, il fonctionne correctement - je peux maintenant naviguer vers les sous-dossiers de la racine de mes projets avec:

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

J'ai réalisé mon erreur en lisant la réponse BaseDirectory vs. Current Directory et @CodeNotFound (qui a été rétractée car elle ne fonctionnait pas à cause de l'erreur ci-dessus), que l'on peut essentiellement trouver ici: Obtention du chemin WebRoot et du chemin racine du contenu dans Asp.net Core

16
akraines

Dans certains cas, _hostingEnvironment.ContentRootPath et System.IO.Directory.GetCurrentDirectory() se dirigent vers le répertoire source. Voici bug à ce sujet.

La solution proposée là-bas m'a aidé

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

Essayez de chercher ici: Meilleur moyen d’obtenir le chemin du dossier de l’application

Pour citer à partir de là:

System.IO.Directory.GetCurrentDirectory() renvoie le répertoire en cours, qui peut être ou non le dossier dans lequel se trouve l'application. Il en va de même pour Environment.CurrentDirectory. Si vous utilisez ceci dans un fichier DLL, il renverra le chemin où le processus est en cours d'exécution (c'est particulièrement vrai dans ASP.NET).

9
shlgug

J'ai résolu le problème avec ce code:

using System.IO;

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