Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASPNETCORE_Environment overrides cmd parameter #17963

Closed
inech opened this issue Dec 19, 2019 · 14 comments
Closed

ASPNETCORE_Environment overrides cmd parameter #17963

inech opened this issue Dec 19, 2019 · 14 comments
Assignees
Labels
area-hosting Includes Hosting area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions
Milestone

Comments

@inech
Copy link

inech commented Dec 19, 2019

Describe the bug

We've noticed a very strange behavior of hosting environment setting. When using ASPNETCORE_Environment="fromEnv" environment variable and --Environment=fromCmd command-line argument then for some reason the environment variable wins.

This is very inconsistent given that:

  1. ASPNETCORE_urls vs --urls - command-line argument wins 📗
  2. DOTNET_ENVIRONMENT vs --Environment - command-line argument wins 📗
  3. ASPNETCORE_ENVIRONMENT vs --Environment - environment variable wins 📙

To Reproduce

  1. (This one works well) When I don't set any environment variables, the command-line argument is applied:
dotnet .\WebApplication_TestEnvironment.dll --Environment=fromCmd
Current environment: fromCmd
  1. (This one works well too) When I set DOTNET_ENVIRONMENT environment variable, the command-line argument wins:
$ENV:DOTNET_ENVIRONMENT="fromDotnetEnv"
dotnet .\WebApplication_TestEnvironment.dll --Environment=fromCmd
Current environment: fromCmd
  1. (This one doesn't work) When I set ASPNETCORE_ENVIRONMENT environment variable, then hosting environment is defined by the environment variable and not by cmd:
$ENV:ASPNETCORE_ENVIRONMENT="fromAspEnv"
dotnet .\WebApplication_TestEnvironment.dll --Environment=fromCmd
Current environment: fromAspEnv

I am able to reproduce it on a newly created ASP.NET Core 3.1 API project. The only small change I did is writing the current environment to the Console .

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

   ....................................................................

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            Console.WriteLine($"Current environment: {env.EnvironmentName}");

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }

Further technical details

dotnet --info
.NET Core SDK (reflecting any global.json):
 Version:   3.1.100
 Commit:    cd82f021f4

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.18362
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\3.1.100\

Host (useful for support):
  Version: 3.1.0
  Commit:  65f04fb6db

.NET Core SDKs installed:
  1.1.9 [C:\Program Files\dotnet\sdk]
  2.1.201 [C:\Program Files\dotnet\sdk]
  2.1.508 [C:\Program Files\dotnet\sdk]
  2.1.509 [C:\Program Files\dotnet\sdk]
  2.1.701 [C:\Program Files\dotnet\sdk]
  2.1.801 [C:\Program Files\dotnet\sdk]
  2.2.109 [C:\Program Files\dotnet\sdk]
  2.2.401 [C:\Program Files\dotnet\sdk]
  3.1.100 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
@mkArtakMSFT mkArtakMSFT added the feature-platform Deprecated: Cross-cutting issues related to ASP.NET Core as a platform label Dec 19, 2019
@vid83
Copy link

vid83 commented May 13, 2020

I noticed a similar behavior with the ASPNETCORE_URLS variable: the value of the "Urls" section of the appsettings.json file always overrides the value of the environment variable.

I stumbled across this problem working on a asp.net 3.1 core application with docker support enabled, where the environment variable was defined in the docker-compose.override.yml file.
Anyway, the same happens in a simple asp.net core 3.1 application, with the environment variable defined in the debug properties of the VS project. In both cases the host was built with the default builder.

Please note that the precedence works exactly as expected with the other variables: environment always wins on the appsettings.json file.

@KoshelevS
Copy link

Any news on this?

I've created the following extension method as a workaround, but it has not been battle-tested yet

        public static IWebHostBuilder FixEnvironmentParam(this IWebHostBuilder webBuilder, string[] args)
        {
            var configBuilder = new ConfigurationBuilder();
            configBuilder.AddCommandLine(args);
            var config = configBuilder.Build();

            var env = config[HostDefaults.EnvironmentKey];
            if (string.IsNullOrWhiteSpace(env))
            {
                return webBuilder;
            }

            return webBuilder.ConfigureAppConfiguration((host, _) => host.HostingEnvironment.EnvironmentName = env)
                             .UseEnvironment(env);
        }

@wtgodbe wtgodbe added affected-few This issue impacts only small number of customers severity-minor This label is used by an internal tool labels Dec 21, 2020
@wtgodbe
Copy link
Member

wtgodbe commented Dec 21, 2020

We will take a look at this in the new year once folks are back from vacation

@BrennanConroy BrennanConroy added feature-hosting and removed feature-platform Deprecated: Cross-cutting issues related to ASP.NET Core as a platform labels Jan 29, 2021
@BrennanConroy BrennanConroy added this to the Next sprint planning milestone Jan 29, 2021
@ghost
Copy link

ghost commented Jan 29, 2021

Thanks for contacting us.
We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We will evaluate the request when we are planning the work for the next milestone. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@mguinness
Copy link

In the documentation under Environment variable configuration provider there is the following sentence which probably explains the behavior reported by the OP.

The default configuration loads environment variables and command-line arguments prefixed with DOTNET_. The DOTNET_ prefix is used by .NET for host and app configuration, but not for user configuration.

@JunTaoLuo JunTaoLuo removed their assignment Aug 6, 2021
@adityamandaleeka adityamandaleeka added the Docs This issue tracks updating documentation label Aug 27, 2021
@adityamandaleeka adityamandaleeka removed this from the 6.0.0 milestone Jan 15, 2022
@halter73
Copy link
Member

#25273 seems related. It has to do with it not being obvious to what URL binding config overrides what.

@adityamandaleeka
Copy link
Member

adityamandaleeka commented Jan 21, 2022

Looks like this behavior is documented here: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-6.0#default-builder-settings

Admittedly, it could be a bit more clear about the fact that config loaded later in the order overrides earlier config.

@adityamandaleeka
Copy link
Member

We should add a clear explanation in our docs of how the config is loaded from various places, in what order, and which things override others.

@Tratcher Tratcher added this to the .NET 7 Planning milestone Feb 4, 2022
@ghost
Copy link

ghost commented Feb 4, 2022

Thanks for contacting us.
We're moving this issue to the .NET 7 Planning milestone for future evaluation / consideration. Because it's not immediately obvious that this is a bug in our framework, we would like to keep this around to collect more feedback, which can later help us determine the impact of it. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@halter73
Copy link
Member

halter73 commented Feb 4, 2022

I think one option here is to give ASPNET_ environment variables the lowest precedence by default. So instead of adding GenericWebHostBuilder's chained config source at the end of the IConfigurationBuilder.Sources, we could add it to the beginning.

if (!options.SuppressEnvironmentConfiguration)
{
configBuilder.AddEnvironmentVariables(prefix: "ASPNETCORE_");
}
_config = configBuilder.Build();
_builder.ConfigureHostConfiguration(config =>
{
config.AddConfiguration(_config);

This would be a breaking change that would likely need to be announced as this would cause DOTNET_ environment variables to
override ASPNETCORE_ environment variables instead of the opposite which happens today, but hopefully there aren't many people relying on that. I'm considering a similar change to WebApplicationBuilder in 7.0 when it's replatted on HostApplicationBuilder or whatever we end up calling it. dotnet/runtime#61634.

@adityamandaleeka
Copy link
Member

adityamandaleeka commented Aug 22, 2022

This should now be addressed in 7 since we did what @halter73 mentioned above.

@ghost ghost locked as resolved and limited conversation to collaborators Sep 22, 2022
@halter73
Copy link
Member

Reopening to consider changing the GenericWebHostBuilder to match WebApplicationBuilder's new behavior of loading ASPNET_-prefixed environment variables with the lowest precedence. We've already made this breaking change to WebApplicationBuilder. See aspnet/Announcements#498

@halter73 halter73 reopened this Nov 18, 2022
@halter73 halter73 removed affected-few This issue impacts only small number of customers Docs This issue tracks updating documentation investigate severity-minor This label is used by an internal tool labels Nov 18, 2022
@halter73 halter73 removed this from the .NET 7 Planning milestone Nov 18, 2022
@adityamandaleeka adityamandaleeka added this to the .NET 8 Planning milestone Nov 21, 2022
@halter73
Copy link
Member

I moved this to preview 1 since it's a relatively small change that we should introduce early since it's breaking.

@adityamandaleeka
Copy link
Member

Triage: this seems low priority and the current behavior is now documented better. Closing this issue.

@adityamandaleeka adityamandaleeka closed this as not planned Won't fix, can't repro, duplicate, stale Feb 1, 2023
@amcasey amcasey added the area-hosting Includes Hosting label Jun 1, 2023
@amcasey amcasey added area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions and removed area-runtime labels Aug 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-hosting Includes Hosting area-networking Includes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions
Projects
None yet
Development

No branches or pull requests