简体   繁体   中英

Proper use of IsDevelopement() on self hosted .net core 2.2 application

I have a self-hosted .NET core 2.2 console app that does not use the web host builder as I do not need HTTP endpoints for this service.

I'm trying to leverage the environment variable through the IsDevelopment() method of the hosting environment but it always comes back as Production .

The following is how I've setup my host builder. I have an environment variable called ASPNETCORE_ENVIRONMENT with a value of Development which leads me to ask two questions.

  1. What is the proper way to have this set when building my own host so that I can conditionally add user secrets to my configuration when building the host?
  2. Second question is if I can use a different environment variable other than ASPNETCORE_ENVIRONMENT since my app is not an ASP.NET core application?

I realize I could probably write code just before building the HostBuilder that explicitly looks for an environment variable and set the environment manually, but ASP.NET Core seems to hook this up behind the scenes so I wanted to see if there was a way to get a similar behavior when I'm not using the web host builder.

private static IHost BuildEngineHost(string[] args)
{
    var engineBuilder = new HostBuilder()
        .ConfigureAppConfiguration((hostContext, config) =>
        {
            config.SetBasePath(Directory.GetCurrentDirectory());
            config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
            config.AddEnvironmentVariables();
            if(hostContext.HostingEnvironment.IsDevelopment())
                config.AddUserSecrets<EngineOptions>();
        })
        .ConfigureServices((hostContext, services) =>
        {
            services.Configure<EngineOptions>(hostContext.Configuration.GetSection("EngineOptions"));
            services.AddHostedService<EtlEngineService>();
        })
        .ConfigureLogging((hostContext, logging) =>
        {
            logging.AddConfiguration(hostContext.Configuration.GetSection("Logging"));
            logging.AddConsole();
        });
    return engineBuilder.Build();
}

UPDATE: The following is needed to configure the host before configuration the application

.ConfigureHostConfiguration(config =>
{
    config.AddCommandLine(args);
    config.AddEnvironmentVariables();
})

This is called before .ConfigureAppConfiguration() and is loaded from any variable called "Environment" which means I don't have to use ASPNET_ENVIRONMENT.

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.2

What is the proper way to have this set when building my own host so that I can conditionally add user secrets to my configuration when building the host?

The proper way is to not have all the lines of code you currently have in your BuildEngineHost method. If you're using ASP.Net Core 2.2, those settings you've wrote are already set for you. In your Program.cs file you should just have this:

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

When you look at CreateDefaultBuilder method implementation on GitHub you will see what you're trying to do is already done by default. This is the implementation of CreateDefaultBuilder :

public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
    var builder = new WebHostBuilder();

    if (string.IsNullOrEmpty(builder.GetSetting(WebHostDefaults.ContentRootKey)))
    {
        builder.UseContentRoot(Directory.GetCurrentDirectory());
    }
    if (args != null)
    {
        builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build());
    }

    builder.ConfigureAppConfiguration((hostingContext, config) =>
    {
        var env = hostingContext.HostingEnvironment;

        config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
              .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

        if (env.IsDevelopment())
        {
            var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
            if (appAssembly != null)
            {
                config.AddUserSecrets(appAssembly, optional: true);
            }
        }

        config.AddEnvironmentVariables();

        if (args != null)
        {
            config.AddCommandLine(args);
        }
    })
    .ConfigureLogging((hostingContext, logging) =>
    {
        logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
        logging.AddConsole();
        logging.AddDebug();
        logging.AddEventSourceLogger();
    }).
    UseDefaultServiceProvider((context, options) =>
    {
        options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
    });

    ConfigureWebDefaults(builder);

    return builder;
}

Anyway if you don't want to use this implementation so to answer to your 2nd question you need to use add this line:

config.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);

Just after this line:

config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

env variable is a type IHostingEnvironment that need to be injected in your BuildEngineHost method.

I was able to have the hosting environment initialized with the correct values by calling ConfigureHostConfiguration() before AppConfiguration which properly sets the environment values in the host which I came across in the following doc from Microsoft.

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-2.2

private static IHost BuildEngineHost(string[] args)
{
    var engineBuilder = new HostBuilder()
        .ConfigureHostConfiguration(config =>
        {
            config.AddEnvironmentVariables();
            config.AddCommandLine(args);
        })
        .ConfigureAppConfiguration((hostContext, config) =>
        {
            config.SetBasePath(Directory.GetCurrentDirectory());
            config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
            config.AddEnvironmentVariables();
            if(hostContext.HostingEnvironment.IsDevelopment())
                config.AddUserSecrets<EngineOptions>();
        })
        .ConfigureServices((hostContext, services) =>
        {
            services.Configure<EngineOptions>(hostContext.Configuration.GetSection("EngineOptions"));
            services.AddHostedService<EtlEngineService>();
        })
        .ConfigureLogging((hostContext, logging) =>
        {
            logging.AddConfiguration(hostContext.Configuration.GetSection("Logging"));
            logging.AddConsole();
        });
    return engineBuilder.Build();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM