How to Get Root Directory of Project in ASP.NET Core. Directory.Getcurrentdirectory() Doesn't Seem to Work Correctly on a Mac

How to get root directory of project in asp.net core. Directory.GetCurrentDirectory() doesn't seem to work correctly on a mac

Depending on where you are in the kestrel pipeline - if you have access to IConfiguration (Startup.cs constructor) or IWebHostEnvironment (formerly IHostingEnvironment) you can either inject the IWebHostEnvironment into your constructor or just request the key from the configuration.

Inject IWebHostEnvironment in Startup.cs Constructor

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

Using IConfiguration in Startup.cs Constructor

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

Directory.GetCurrentDirectory() doesn't return the correct directory

This is a bug in ASP.NET Core 2.2 which has been reported in GitHub and Microsoft ASP.NET Core team has provided a solution as follows and they will add this solution to the feature release of ASP.NET Core.

Write a helper class as follows:

public class CurrentDirectoryHelpers
{
internal const string AspNetCoreModuleDll = "aspnetcorev2_inprocess.dll";

[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);

[System.Runtime.InteropServices.DllImport(AspNetCoreModuleDll)]
private static extern int http_get_application_properties(ref IISConfigurationData iiConfigData);

[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
private struct IISConfigurationData
{
public IntPtr pNativeApplication;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
public string pwzFullApplicationPath;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.BStr)]
public string pwzVirtualApplicationPath;
public bool fWindowsAuthEnabled;
public bool fBasicAuthEnabled;
public bool fAnonymousAuthEnable;
}

public static void SetCurrentDirectory()
{
try
{
// Check if physical path was provided by ANCM
var sitePhysicalPath = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_PHYSICAL_PATH");
if (string.IsNullOrEmpty(sitePhysicalPath))
{
// Skip if not running ANCM InProcess
if (GetModuleHandle(AspNetCoreModuleDll) == IntPtr.Zero)
{
return;
}

IISConfigurationData configurationData = default(IISConfigurationData);
if (http_get_application_properties(ref configurationData) != 0)
{
return;
}

sitePhysicalPath = configurationData.pwzFullApplicationPath;
}

Environment.CurrentDirectory = sitePhysicalPath;
}
catch
{
// ignore
}
}
}

Then call the SetCurrentDirectory() method in your code as follows:

app.UseStaticFiles(new StaticFileOptions {
FileProvider = new PhysicalFileProvider(

CurrentDirectoryHelpers.SetCurrentDirectory(); // call it here

Path.Combine(Directory.GetCurrentDirectory(), "StaticFiles")),
RequestPath = "/StaticFiles"
});

Now everything should work fine!

Best way to get application folder path

AppDomain.CurrentDomain.BaseDirectory is probably the most useful for accessing files whose location is relative to the application install directory.

In an ASP.NET application, this will be the application root directory, not the bin subfolder - which is probably what you usually want. In a client application, it will be the directory containing the main executable.

In a VSTO 2005 application, it will be the directory containing the VSTO managed assemblies for your application, not, say, the path to the Excel executable.

The others may return different directories depending on your environment - for example see @Vimvq1987's answer.

CodeBase is the place where a file was found and can be a URL beginning with http://. In which case Location will probably be the assembly download cache. CodeBase is not guaranteed to be set for assemblies in the GAC.

UPDATE
These days (.NET Core, .NET Standard 1.3+ or .NET Framework 4.6+) it's better to use AppContext.BaseDirectory rather than AppDomain.CurrentDomain.BaseDirectory. Both are equivalent, but multiple AppDomains are no longer supported.



Related Topics



Leave a reply



Submit