How to set ASPNETCORE_ENVIRONMENT for console application? - c#

I have the following simple console application that contains a hosted service:
public static async Task Main(string[] args)
{
using (var host = Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
// db context
services.AddEntityFrameworkNpgsql()
.AddDbContext<ApplicationDbContext>();
// hosted services
services.AddHostedService<ConsumeScopedServiceHostedService>();
services.AddScoped<ProcessManuallySendings>();
// services
services.AddHttpClient<ISendPushService, SendPushService>(x
=>
{
x.Timeout = TimeSpan.FromSeconds(65);
});
})
.Build())
{
// Start the host
await host.StartAsync();
// Wait for the host to shutdown
await host.WaitForShutdownAsync();
}
}
}
It works with my database and it means that it requires connection string. I have three appsettings.json files:
On the development server I will use Development environment, on the production - Production. On my local machine I'm going to use Local. It's simple.
I'm going to get it with the help of ASPNETCORE_ENVIRONMENT (OS environment variable).
I use Linux and in my shell (zsh) config file I have:
When I type in my terminal $ echo $ASPNETCORE_ENVIRONMENT I have Local.
But when I start my console application
$ dotnet run // in the project folder
It's trying to start with Production environment.
See debug output:
So how to set environment? Why Os variable doesn't work?

According to the docs for .Net Core 3.0 onwards, the host configuration is provided from environment variables prefixed with DOTNET_ (for example, DOTNET_ENVIRONMENT).
If that doesn't work, you could also try setting the environment variable in the launchSettings.json like this on your profile.
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT" : "Development"
}

With .NET Core 3, the generic host uses the DOTNET_ prefix, not the old ASPNETCORE_ prefix.

When setting environment variables in rider for a console application in dotnet core 3.1, neither ASPNETCORE_ENVIRONMENT nor DOTNET_ENVIRONMENT worked regardless of whether they were set in the Run/Debug Configuration or LaunchSettings.
In my situation, I am using Microsoft.Extensions.Hosting and Microsoft.Extensions.Hosting.Abstractions and wanted hostEnvironment to be resolved correctly to Development.
if (hostEnvironment.IsDevelopment())
{
optionsBuilder.EnableSensitiveDataLogging();
optionsBuilder.AddInterceptors(new EfCommandInterceptor());
}
To get this working, I had to create an environment variable called ENVIRONMENT with the appropriate value.
ENVIRONMENT=Development

Related

.NET - How to force app to get Environment Variables from launchSettings.json instead of appSettings.Development.json when running the app locally?

I saw in this answer (link #1) that I can add my DB connection string in launchSettings.json instead of appsettings as an environment variable (for local development purposes).
Our appsettings.Development.json is reserved for publishing, deploying and testing our company's app in the Development environment, not for running the app in my local development environment (ie. Visual Studio). So our Development environment is actually a dev test environment.
How do I force the app to get the connection string Environment Variable from launchSettings.json (as show in the link #1) instead of appSettings.Development.json when running the app in my LOCAL development environment (i.e. via Visual Studio)? Question 1: Is there an IConfiguration method to do that forcing?
I am thinking I could do something in my code like:
string connectionString;
if (_configuration.forceGetFromLaunchSettings("ConnectionString") == null) {
connectionString = _config.GetValue<int>("AppSettings:ConnectionString"); // This will run in the Dev (test) environment
}
else {
connectionString = _configuration.forceGetFromLaunchSettings("ConnectionString"); // This will run in the local (Visual Studio) environment.
}
👆 So is there any pre-existing IConfiguration method like .forceGetFromLaunchSettings()
Question 2: If the above does not work or is too janky of a solution, do I need create a separate appsettings.Local.json file to hold my local appsettings? If yes, then how do I run the app in Visual Studio using that new appsetting file?
PS: If both of the above solutions are jank, please suggest a different one.

Docker specific settings

I have configurations that are environment specific. For instance, a path that I want to access when debugging the project via IIS, be in C:\MyApp\MyLocation, but when debugging the project in Docker, will be ine \app\something.
My plan was to have a specific appsettings.json for this type of build. So, where I would normally have the C:\MyApp\MyLocation in my appsettings.development.json, I would create a appsettings.docker.json, put the setting in there, and then add/change the environmental variable for "ASPNETCORE_ENVIRONMENT" to 'docker'.
However, this plan did not work, as I now get this message when I debug my app via Docker :
System.InvalidOperationException: 'Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found or is out of date.
To generate a developer certificate run 'dotnet dev-certs https'. To trust the certificate (Windows and macOS only) run 'dotnet dev-certs https --trust'.
For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.'
Is there any way I can get it work in this manner, or any other way I can docker specific configurations?
Edit:
Actually after re-reading your question and correctly reading the error, I can see that your issue has nothing to do with the configurations.
Your Asp.Net App is configured to use the developer certificate for HTTPS. Either you deactivate by removing the AddAuthentication and UseAuthentication or you have to install the certificate on the Docker image.
You can use dotnet dev-certs https in your DOCKERFILE before running your app temporarily, but in the future should create a real HTTPS certificate and configure your app correctly.
See https://learn.microsoft.com/en-us/aspnet/core/security/authentication/certauth?view=aspnetcore-3.1
You've tagged your question with .Net Core, so I guess that you're using it.
If so, you should probably be reading configurations through Configuration providers. And if your application startup is done this way:
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>();
});
}
It will load the json configuration provider and then the environment variables configuration provider. This means that any value that you have in your json configuration file can and will be overrided by environment variables that matches the json key correctly.
It's very easy to set environment variables when starting Docker image, and it's usually the preferred way to go when you want to set configuration of Docker images.
The hierarchy is usually set by separating the parts with __.
set MyKey="My key from Environment"
set Position__Title=Environment_Editor
set Position__Name=Environment_Rick
dotnet run
More information on the documentation.

How to set hosting environment name for .NET Core console app using Generic Host (HostBuilder)

I am setting up a .NET Core 2.x console app as a Windows service and need to load an appsettings json file based on the environment. I was thinking to start the service with a command line argument that identifies the environment. How can I do that in Visual Studio? No matter what I set in the project settings, the EnvironmentName value is always "Production".
How can I set my environment from a command line argument?
var hostBuilder = new HostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddCommandLine(args);
config.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: false, reloadOnChange: true);
config.AddEnvironmentVariables();
})
.ConfigureServices((hostContext, services) =>
{
//Inject additional services as needed
services.AddHostedService<JobRunner>();
});
You can set the environment from the command line variables via the ConfigureHostConfiguration extension method.
Set up the configuration for the builder itself. This will be used to
initialize the Microsoft.Extensions.Hosting.IHostEnvironment for use
later in the build process.
var hostBuilder = new HostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureHostConfiguration(configurationBuilder => {
configurationBuilder.AddCommandLine(args);
})
.ConfigureAppConfiguration((hostingContext, cfg) =>
{
// ...
var env = hostingContext.HostingEnvironment;
Console.WriteLine(env.EnvironmentName); // Test
// ...
});
// ...
hostBuilder.Build();
In Visual Studio, you configure the application arguments with the same ones as being used by dotnet run which is --environment,
e.g. dotnet run --environment Test.
Without this application argument, the hosting environment defaults back to Production.
In Visual Studio, you can add an environment variable under the Debug tab of the console application properties. For a console application the environment variable provider name must be prefixed by DOTNET_ for the generic host builder to recognize it. In this case, the provider name is DOTNET_ENVIRONMENT.
If this provider name is not specified, the default is Production.
Reference : https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-5.0#host-configuration
Another method is to use the "UseEnvironnement" method directly on the host builder :
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.hostinghostbuilderextensions.useenvironment?view=dotnet-plat-ext-5.0
For example :
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseEnvironment("dev") // Magic is here
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseUrls("http://0.0.0.0:8081");
webBuilder.UseStartup<Startup>();
});
To add to pfx's accepted answer above, in Visual studio 2022, the environment variable can be set either via Properties window in UI:
or set the environment variable:
or directly edit the launchSettings.json file under Properties and add command line arguement:
If you are using Visual Studio 2022 with .Net 5, the UI could be a bit overwhelming. Its simple to edit launchSettings.json file under properties.
Mine looks as follows. Note its DOTNET_ENVIRONMENT and NOT ASPNETCORE_ENVIRONMENT for .NET Core console app using Generic Host (HostBuilder)
{
"profiles": {
"Bvh.HrSita.DbMigrator": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
},
"Bvh.HrSita.DbMigrator.Prod": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Production"
}
},
"Bvh.HrSita.DbMigrator.Stag": {
"commandName": "Project",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Staging"
}
},
"Docker": {
"commandName": "Docker"
}
}
}
Now select what ever profile you want when you launch the project. The following shows it all along with Program.cs.
And finally if you are trying to run the same in an Azure DevOps pipeline, the task should be as shown below. The arguments should have --environment Production. Note that adding env: is somehow NOT working for me as suggested here.
- task: DotNetCoreCLI#2
displayName: 'Run DbMigrator Project on the newly provisoned database'
inputs:
command: run
projects: '$(Pipeline.Workspace)/$(finalBuildArtifactName)/src/Bvh.HrSita.DbMigrator/Bvh.HrSita.DbMigrator.csproj'
arguments: '--configuration $(BuildConfiguration) --environment Production'
env:
DOTNET_ENVIRONMENT: Production
To pick up the hosting environment from environment variables, you can also add:
.ConfigureHostConfiguration(config =>
{
config.AddEnvironmentVariables();
})
Then use Environment environment variable to pass the actual environment.
If you are using visual studio and you have project configuration (Debug, Release, CustomUser...)
then you could include appsettings.[config-name].json like this:
Host
.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, builder) => {
//add visual studio configuration manager
builder.AddJsonFile($"appSettings.{Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyConfigurationAttribute>().Configuration}.json", true);
...
})
...
In Visual Studio 2022 and .NET 6.0, appsettings.json and appsettings.[EnvironmentName].json are automatically included in configuration sources when using HostBuilder:
So there is no need to manually add these in ConfigureServices.
You still need to set EnvironmentName in launchSettings.json or as a commandline argument as shown in the other answers.
I run into this issue time and time again and can never remember what my solution was from the previous time I ran into it. Typically, I'm simply trying to get a Development and Production environment in my console app like you get by default with a web app (configured with launchSettings.json and other more buried mechanisms).
At the beginning of my Program.cs in my console app, I add:
#if DEBUG
Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", "Development");
#endif
var env = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT") ?? "Production";
Console.WriteLine($"{env}");
However, you could also just as easily define your environment outright with the debug condition:
var env = "Production";
#if DEBUG
env = "Development";
#endif
Console.WriteLine($"{env}");
You can also set your EnvironmentName like this:
var host = Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
#if DEBUG
context.HostingEnvironment.EnvironmentName = "Development";
#endif
var env = context.HostingEnvironment.EnvironmentName;
Console.WriteLine(env);
config.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.{env}.json", optional: true);
}).Build();
It's not command line, but should work as a solution. I also rarely see this suggested and found this digging through one of my older projects (after hours of searching online), so I'm not sure if it has any downsides (other than mostly only being good for one other environment besides Production)? Please leave a comment if there are other gotchas. It's definitely the easiest to implement for a console app.
Part of the reason for posting this answer also is so my future self can hopefully find it more quickly than this time around.

ASP.NET Core set hosting environment in build process

I have an ASP.NET Core Api where I use the appsettings.{environmentname}.json configuration files. Then I also have the appropriate launchSettings.json file with the different environment options so I can run with any specific environment settings file.
In the Startup.cs, we have a conditional setting where if we are in a non-prod environment, then we use a specific set of Jwt authentication (just has some validating checks turned off), then in prod, we load a different version that has all of the checks to turn on.
On my localhost, this works great where environment.IsDevelopment() returns true, while environment.IsProduction() returns false. Great!
But, when I run this through our build process and deploy to our test environment, the environment.IsDevelopment() now returns false.
I have added in the option in the Program.cs file to add the ConfigurationBuilder so I can pass variables to my build process, which looks like this:
dotnet restore
dotnet build --environment "Development"
dotnet publish -o ..\Artifacts
I'll post the relevant files, and the associated code for more info...
Program.cs
public static IWebHost BuildWebHost(string[] args)
{
var config = new ConfigurationBuilder()
.AddCommandLine(args)
.Build();
return WebHost.CreateDefaultBuilder(args)
.UseConfiguration(config)
.UseStartup<Startup>()
.UseNLog()
.Build();
}
Startup.cs (ConfigureServices method)
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
// removed code not relevant...
// options.TokenValidationParameters = Environment.IsProduction()
// options.TokenValidationParameters = Environment.IsEnvironment("Prod")
options.TokenValidationParameters = Environment.IsDevelopment()
? devTokenValidationParameters
: prodTokenValidationParameters;
// options.TokenValidationParameters = devTokenValidationParameters;
});
Why are the helper environment.Is{EnvironmentName}() checks not working here?
The environment name is runtime concept rather than a compile (or build) time concept. This means that when building (or publishing) an application the environment is not yet known and setting is has no effect. Your code is not running when you publish the application.
You can control the environment name when running the application e.g. via an argument of dotnet run:
dotnet run --environment=Production
Or using a known environment variable ASPNETCORE_ENVIRONMENT. For example by executing this at the command line:
set ASPNETCORE_ENVIRONMENT=Production
This variable might also be set using the launchSettings.json file for debugging purposes. This file is generated when creating a new project using Visual Studio or dotnet new.
The default environment for an application is Production. Please refer to the documentation for more info about this topic.

Cannot find module 'aspnet-webpack' when using 'dotnet publish' in .Net Core 2.0 & Angular

I have been trying to follow answers to this problem but to no avail.. I am trying to publish my .Net Core 2.0 & Angular project using the command line command 'dotnet publish' I successfully publish, however when trying to run my project's .dll in the published folder, my project spits in out this error when run in a development environment:
Unhandled Exception: System.AggregateException: One or more errors occurred. (Webpack dev middleware failed because of an error while loading 'aspnet-webpack'. Error was: Error: Cannot find module 'aspnet-webpack'
When run in Production and allowing for the DeveloperExceptionPage (as shown in my statup.cs below) the .netcore app runs, but crashes within the actual web app, which I assume is due to the larger error, aspnet-webpack not being found:
NodeInvocationException: Uncaught (in promise): Error: No component factory found for HomeComponent. Did you add it to #NgModule.entryComponents?
Startup.cs
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.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
}
else
{
//app.UseExceptionHandler("/Home/Error");
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
}
}
I am not using #Angular/Cli, but I am using the default Angular Project that VS2017 (August update, I believe?) generates, which seems to only use Webpack. The problem seems to be that the Production config of the project expects a reference that I am not providing, but I can not figure out why that is.
No other answers to this question have helped me thus far, so I apologize if this is a repeat question.
After you publish your .Net Core 2.0 & Angular project, and before you run it, you need to ensure that the environment variable ASPNETCORE_ENVIRONMENT isn't set to Development. The published project doesn't include support for the WebpackDevMiddleware or HotModuleReplacement. But it will attempt to use them if the environment is set to Development.
HotModuleReplacement automatically updates Webpack-built resources (such as JavaScript, CSS, or images) in your web browser whenever source files are changed. This is obviously something that you don't want in production.
If ASPNETCORE_ENVIRONMENT is set to "Development", you can change the setting with:
setx ASPNETCORE_ENVIRONMENT "Production"
You will need to close the current command window and open another to see the change.
You can also comment out the following code in startup.cs to accomplish the same result:
#if DEBUG
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
#endif
Make sure you have fully installed all of these dependencies:
npm install webpack-hot-middleware --save-dev
npm install webpack-dev-middleware --save-dev
npm install aspnet-webpack --save-dev
In my case the cause was that the SPA (Vue in my case) is in the ClientApp folder and app.UseWebpackDevMiddleware expects it to be in the project root.
Setting the ProjectPath option solved this for me.
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true,
ConfigFile = Path.Combine(env.ContentRootPath, #"ClientApp\node_modules\#vue\cli-service\webpack.config.js"),
ProjectPath = Path.Combine(env.ContentRootPath, #"ClientApp")
});
I had same issue with "aspnet-webpack", this was introduced halfway in the project development so I was bit surprised to see sudden death of the solution. It was all working fine couple of months on IIS but suddenly failed to boot.
IIS log files were not helpful, so I tried to resolve this couple of ways, one of them worked. Hurry!
Solution
I ran following on package-manager window :
dotnet run --project <Full path of *.csproj> --configuration Debug
It give me some pointers and I started searching for "Error: Cannot find module 'aspnet-webpack'" issue. I tried to go through all the changes for last couple of check-ins, and found out that we updated the "Microsoft.AspNetCore.All" from 2.0.0 to 2.0.3 version, so downgrading it to original version fixed it.
I guess they both uses different versions of node packages. So don't update for sake unless for a very good reason. Reading around this some bits are very tightly coupled to specific versions and Angular very easily breaks, if something changed. In process though I have managed to upgrade the node version to latest 5.0.0
Love to find more details, but for time being no details on why it needs a specific version.
I got the same error as you in a project without Angular:
Unhandled Exception: System.AggregateException: One or more errors occurred. (Webpack dev middleware failed because of an error while loading 'aspnet-webpack'. Error was: Error: Cannot find module 'aspnet-webpack'
Turned out to be a simple problem with node that I tend to forget.
npm install
Remember that npm commands need to be run in the top directory which contains your package.json file. I hope that this helps someone who has as much problems as me remembering to actually run npm commands. Thanks to the forum which reminded me:
https://www.ebenmonney.com/forum/?view=thread&id=20&part=1#postid-57
Check that node.js is installed in production and is in the path.
Node.js is used by webpack
Also check that you have a recent version of Node.js (4+)
Reference : AspNetCore + Angular 2: WebpackDevMiddleware Error with new project
Version of Node.js can be checked with :
where.exe node.exe (Windows 7+)
which node.exe (linux bash)
And of course path environment variable should be checked and updated if pointing to obsolete Node.js
All the best
AT configure function of startup.cs You can use if statement for development environment
if (env.IsDevelopment())
{
// Print exception and all details for the developer
app.UseDeveloperExceptionPage();
// Use WebPack to update css , js , html automatically
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
You can this comman in command print to change current environment :
setx ASPNETCORE_ENVIRONMENT "Development"
The main reason for this error is that you are using a dependency somewhere in your code and it isn't installed in your solution. If you are using visual studio, try using clean build, it will show up the errors in your project which'll help you in finding it.

Categories