Hoe u een absoluut pad op een alternatieve ASP-netcore-manier kunt krijgen voor Server.MapPath
Ik heb geprobeerd IHostingEnvironment
te 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 IWebHostEnvironment
om toegang te krijgen tot het WebRootPath
dat is verplaatst naar de webspecifieke omgevingsinterface.
Injecteer IWebHostEnvironment
als 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 IPathProvider
in 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_Name
waar 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 IHostingEnvironment
is 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 IWebHostEnvironment
gebruiken 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 IFileProvider
vind 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 IFileProvider
maken 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 IFileProvider
van startup.cs
en dan zou ik gewoon GetFileInfo()
kunnen gebruiken zoals ik MapPath
in het verleden.