TheHvidsten
TheHvidsten

Reputation: 4428

Starting ASP.NET Core from Visual Studio doesn't start from build folder

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

Answers (3)

alim
alim

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

Ilya Chernomordik
Ilya Chernomordik

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:

  1. 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?

  2. Not using CreateDefaultBuilder and creating the builder yourself, then you'll be able to configure it exactly as you want.

  3. 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

  4. 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

michael_c_p
michael_c_p

Reputation: 82

Maybe this will help is set to directory as application working directory by:

Directory.SetCurrentDirectory(context.HostingEnvironment.ContentRootPath);

Upvotes: 0

Related Questions