Reputation: 4428
When you start an ASP.NET Core project from Visual Studio (2017) it assumes the working directory is where the source code is located, not where the built files are actually placed.
Which means that when I run my project it reads the config file from C:\Path\To\My\Project\appsettings.json
, and not from C:\Path\To\My\Project\bin\Debug\appsettings.json
.
I can see that this is the case when I debug this code:
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureAppConfiguration((context, config) => {
config.SetBasePath(context.HostingEnvironment.ContentRootPath);
config.AddJsonFile("appsettings.json", true, false);
});
Where ContentRootPath
points to the project folder, not where the built files are placed.
I could probably fix this by setting the Working Directory
in Project Properties > Debug
, but seeing as we're also using configuration transforms (SlowCheetah), each developer will have their own build configuration for debug output (bin\Debug[CustomConfiguration]
), and changing .csproj
for one developer breaks it for all the other developers.
Is there any way of having ASP.NET Core read the config files from where the built files are placed instead of the project folder, without having to change the Working Directory
, yet still working for multiple "Build Configurations"?
Upvotes: 8
Views: 2100
Reputation: 747
If I understand the problem correctly, every developer has a different output folder with respect to their username. So, if you make up something like this,
var debug = string.Empty;
#if DEBUG
debug = "Debug";
#else
debug = "Release";
#endif
var userNameVariable = System.Environment.GetEnvironmentVariable("USER");
debug += $"[{userNameVariable}]";
var path = System.IO.Path.Combine(env.ContentRootPath, "bin", debug);
var builder = new ConfigurationBuilder()
.SetBasePath(path) //env.ContentRootPath
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
I have tested this on Mac OS and result is
/Users/johndoe/Documents/Temp/contentasp/bin/Debug[johndoe]
Other solution.
In visual studio you have pre-build and post-build scripts. In Visual Studio you can get the OutputFolder and set the path into a environment variable on pre-build script. For example:
powershell.exe -ExecutionPolicy Bypass -File "$(ProjectDir)outputscript.ps1" -OutputFolder $(OutputPath)
And in the powershell script (outputscript.ps1
)
Param(
[Parameter(Mandatory = $true, Position = 1)]
[string]$OutputFolder
)
$env:OutputFolder = $OutputFolder
And you can get the value on the startup with
var outputFolder = System.Environment.GetEnvironmentVariable("OutputFolder");
var builder = new ConfigurationBuilder()
.SetBasePath(outputFolder) //env.ContentRootPath
Upvotes: 1
Reputation: 30205
Config files are read from the place that you configure via SetBasePath
. What happens in Development mode is that when you use WebHost.CreateDefaultBuilder
it sets BasePath
to source code folder which is logical for most developer cases.
It actually does not work out of the box for Console applications e.g., so I specifically do the same in there.
There are probably few ways you can fix this:
Using the existing system as it is quite convenient by default. Perhaps you can explain in more details why does it not work for you?
Not using CreateDefaultBuilder
and creating the builder yourself, then you'll be able to configure it exactly as you want.
Override SetBasePath
with the value you want afterwards. I assume that e.g. AppContext.BaseDirectory
or Directory.GetCurrentDirectory()
will return the path that you are looking for
Not using name "Development" for your environment will probably do the trick as well, though you will have some other consequences that you need to consider.
P.S. Why would you use slowcheetah at all to do the old styled transformation when you can use agile config? You can read config from multiple files and the last one in order always win, so it will be the same effect as from using slowcheetah in practice.
Upvotes: 0
Reputation: 82
Maybe this will help is set to directory as application working directory by:
Directory.SetCurrentDirectory(context.HostingEnvironment.ContentRootPath);
Upvotes: 0