web-dev-qa-db-fra.com

Comment obtenir un chemin absolu dans une manière alternative d'ASP.Net Core pour Server.MapPath

Comment obtenir un chemin absolu dans ASP autre moyen de base du réseau pour Server.MapPath

J'ai essayé d'utiliser IHostingEnvironment mais cela ne donne pas un résultat correct.

IHostingEnvironment env = new HostingEnvironment();
var str1 = env.ContentRootPath; // Null
var str2 = env.WebRootPath; // Null, both doesn't give any result 

J'ai un fichier image (Sample.PNG) dans le dossier wwwroot Je dois obtenir ce chemin d'accès absolu.

26
Shanmu_92

Injectez IHostingEnvironment comme dépendance dans la classe dépendante. Le cadre le peuplera pour vous

public class HomeController : Controller {
    private IHostingEnvironment _hostingEnvironment;

    public HomeController(IHostingEnvironment environment) {
        _hostingEnvironment = environment;
    }

    [HttpGet]
    public IActionResult Get() {
        var path = Path.Combine(_hostingEnvironment.WebRootPath, "Sample.PNG");
        return View();
    }
}

Vous pouvez aller plus loin et créer votre propre abstraction et implémentation de services de fournisseur de chemin d'accès.

public interface IPathProvider {
    string MapPath(string path);
}

public class PathProvider : IPathProvider {
    private IHostingEnvironment _hostingEnvironment;

    public PathProvider(IHostingEnvironment environment) {
        _hostingEnvironment = environment;
    }

    public string MapPath(string path) {
        var filePath = Path.Combine(_hostingEnvironment.WebRootPath, path);
        return filePath;
    }
}

Et injectez IPathProvider dans les classes dépendantes.

public class HomeController : Controller {
    private IPathProvider pathProvider;

    public HomeController(IPathProvider pathProvider) {
        this.pathProvider = pathProvider;
    }

    [HttpGet]
    public IActionResult Get() {
        var path = pathProvider.MapPath("Sample.PNG");
        return View();
    }
}

Assurez-vous d'enregistrer le service avec le conteneur DI

services.AddSingleton<IPathProvider, PathProvider>();
74
Nkosi

* Hack * Non recommandé, mais pour votre information, vous pouvez obtenir un chemin absolu à partir d'un chemin relatif avec var abs = Path.GetFullPath("~/Content/Images/Sample.PNG").Replace("~\\","");

Préférez les approches DI/Service ci-dessus, mais si vous vous trouvez dans une situation autre que DI (par exemple, une classe instanciée avec Activator), cela fonctionnera.

5
Randy Buchholz

Une meilleure solution consiste à utiliser la méthode IFileProvider.GetFileInfo().

    public IActionResult ResizeCat([FromServices] IFileProvider fileProvider)
    {
        // get absolute path (equivalent to MapPath)
        string absolutePath = fileProvider.GetFileInfo("/assets/images/cat.jpg").PhysicalPath;  
        ... 
    }

Vous devez vous enregistrer IFileProvidercomme ceci pour pouvoir y accéder via DI :

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc();

        var physicalProvider = _hostingEnvironment.ContentRootFileProvider;
        var embeddedProvider = new EmbeddedFileProvider(Assembly.GetEntryAssembly());
        var compositeProvider = new CompositeFileProvider(physicalProvider, embeddedProvider);

        // choose one provider to use for the app and register it
        //services.AddSingleton<IFileProvider>(physicalProvider);
        //services.AddSingleton<IFileProvider>(embeddedProvider);
        services.AddSingleton<IFileProvider>(compositeProvider);
    }

Comme vous pouvez le constater, cette logique (d'où provient un fichier) peut devenir assez complexe, mais votre code ne sera pas cassé s'il change.

Vous pouvez créer un IFileProvider personnalisé avec new PhysicalFileProvider(root) si vous avez une logique particulière. Je souhaitais charger une image dans un middleware et la redimensionner ou la rogner. Mais il s’agit d’un projet Angular), de sorte que le chemin est différent pour une application déployée. Le middleware que j’ai écrit prend IFileProvider à partir de startup.cs, Puis je pourrais simplement utiliser GetFileInfo() comme j'aurais utilisé MapPath dans le passé.

3
Simon_Weaver

Merci à @NKosi mais IHostingEnvironment est obsolète dans le noyau 3 de MVC !!

selon this :

Types obsolètes (avertissement):

Microsoft.Extensions.Hosting.IHostingEnvironment
Microsoft.AspNetCore.Hosting.IHostingEnvironment
Microsoft.Extensions.Hosting.IApplicationLifetime
Microsoft.AspNetCore.Hosting.IApplicationLifetime
Microsoft.Extensions.Hosting.EnvironmentName
Microsoft.AspNetCore.Hosting.EnvironmentName

Nouveaux types:

Microsoft.Extensions.Hosting.IHostEnvironment
Microsoft.AspNetCore.Hosting.IWebHostEnvironment : IHostEnvironment
Microsoft.Extensions.Hosting.IHostApplicationLifetime
Microsoft.Extensions.Hosting.Environments 

Vous devez donc utiliser IWebHostEnvironment au lieu de IHostingEnvironment.

public class HomeController : Controller
{
    private readonly IWebHostEnvironment _webHostEnvironment;

    public HomeController(IWebHostEnvironment webHostEnvironment)
    {
        _webHostEnvironment= webHostEnvironment;
    }

    public IActionResult Index()
    {
        string webRootPath = _webHostEnvironment.WebRootPath;
        string contentRootPath = _webHostEnvironment.ContentRootPath;

        return Content(webRootPath + "\n" + contentRootPath);
    }
}
2
amir133