Hoe een absoluut pad te krijgen in ASP.Net Core alternatieve manier voor Server.MapPath

Hoe u een absoluut pad op een alternatieve ASP-netcore-manier kunt krijgen voor Server.MapPath

Ik heb geprobeerd IHostingEnvironmentte gebruiken, maar het geeft geen goed resultaat.

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

Ik heb één afbeeldingsbestand (Sample.PNG) in de map wwwroot. Ik heb dit absolute pad nodig.


Antwoord 1, autoriteit 100%

Vanaf .Net Core v3.0 zou dit IWebHostEnvironmentom toegang te krijgen tot het WebRootPathdat is verplaatst naar de webspecifieke omgevingsinterface.

Injecteer IWebHostEnvironmentals een afhankelijkheid in de afhankelijke klasse. Het raamwerk zal het voor u invullen

public class HomeController : Controller {
    private IWebHostEnvironment _hostEnvironment;
    public HomeController(IWebHostEnvironment environment) {
        _hostEnvironment = environment;
    }
    [HttpGet]
    public IActionResult Get() {
        string path = Path.Combine(_hostEnvironment.WebRootPath, "Sample.PNG");
        return View();
    }
}

Je zou nog een stap verder kunnen gaan en je eigen abstractie en implementatie van een path provider-service maken.

public interface IPathProvider {
    string MapPath(string path);
}
public class PathProvider : IPathProvider {
    private IWebHostEnvironment _hostEnvironment;
    public PathProvider(IWebHostEnvironment environment) {
        _hostEnvironment = environment;
    }
    public string MapPath(string path) {
        string filePath = Path.Combine(_hostEnvironment.WebRootPath, path);
        return filePath;
    }
}

En injecteer IPathProviderin afhankelijke klassen.

public class HomeController : Controller {
    private IPathProvider pathProvider;
    public HomeController(IPathProvider pathProvider) {
        this.pathProvider = pathProvider;
    }
    [HttpGet]
    public IActionResult Get() {
        string path = pathProvider.MapPath("Sample.PNG");
        return View();
    }
}

Zorg ervoor dat u de service registreert met de DI-container

services.AddSingleton<IPathProvider, PathProvider>();

Antwoord 2, autoriteit 7%

* Hacken *
Niet aanbevolen, maar ter informatie: je kunt een absoluut pad krijgen van een relatief pad met

var abs = Path.GetFullPath("~/Content/Images/Sample.PNG").Replace("~\\","");

Geef de voorkeur aan de DI/Service-benaderingen hierboven, maar als u zich in een niet-DI-situatie bevindt (bijv. een klasse die is geïnstantieerd met Activator), zal dit werken.


Antwoord 3, autoriteit 7%

.NET Core 3.0

Var 1:

string path = System.IO.Directory.GetCurrentDirectory();

Var 2:

string path = AppDomain.CurrentDomain.BaseDirectory.Substring(0, AppDomain.CurrentDomain.BaseDirectory.IndexOf("\\bin"));

Antwoord 4, autoriteit 5%

.Net Core 3

Ik wil bijvoorbeeld ~/wwwroot/CSS

. vinden

public class YourController : Controller 
{
    private readonly IWebHostEnvironment _webHostEnvironment;
    public YourController (IWebHostEnvironment webHostEnvironment)
    {
        _webHostEnvironment= webHostEnvironment;
    }
    public IActionResult Index()
    {
        string webRootPath = _webHostEnvironment.WebRootPath;
        string contentRootPath = _webHostEnvironment.ContentRootPath;
        string path ="";
        path = Path.Combine(webRootPath , "CSS");
        //or path = Path.Combine(contentRootPath , "wwwroot" ,"CSS" );
        return View();
    }
}

Enkele trucs

Ook als je geen controller of service hebt, volg dan de laatste Part en registreer de klasse als singleton.
Dan, in Startup.ConfigureServices:

services.AddSingleton<your_class_Name>();

Injecteer ten slotte your_class_Namewaar je het nodig hebt.


.Net Core 2

Ik wil bijvoorbeeld ~/wwwroot/CSS

. vinden

public class YourController : Controller
{
    private readonly IHostingEnvironment _HostEnvironment;
    public YourController (IHostingEnvironment HostEnvironment)
    {
        _HostEnvironment= HostEnvironment;
    }
    public ActionResult Index()
    {
        string webRootPath = _HostEnvironment.WebRootPath;
        string contentRootPath = _HostEnvironment.ContentRootPath;
        string path ="";
        path = Path.Combine(webRootPath , "CSS");
        //or path = Path.Combine(contentRootPath , "wwwroot" ,"CSS" );
        return View();
    }
}

Meer details

Dankzij @NKosi maar IHostingEnvironmentis verouderd in MVC core 3!!

volgens dit:

Verouderde typen (waarschuwing):

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

Nieuwe typen:

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

Je moet dus IWebHostEnvironmentgebruiken in plaats van IHostingEnvironment.


Antwoord 5, autoriteit 3%

Een betere oplossing is om de methode IFileProvider.GetFileInfo()te gebruiken.

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

U moet IFileProvidervind dit leuk om toegang te krijgen 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);
    }

Zoals je kunt zien, kan deze logica (voor waar een bestand vandaan komt) behoorlijk ingewikkeld worden, maar je code zal niet breken als deze verandert.

Je kunt een aangepaste IFileProvidermaken met new PhysicalFileProvider(root)als je een speciale logica hebt. Ik had een situatie waarin ik een afbeelding in middleware wilde laden en het formaat wilde wijzigen of bijsnijden. Maar het is een Angular-project, dus het pad is anders voor een geïmplementeerde app. De middleware die ik schreef neemt IFileProvidervan startup.csen dan zou ik gewoon GetFileInfo()kunnen gebruiken zoals ik MapPathin het verleden.

Other episodes