How to have a config file for local development and one for the development server in AspNet Core without breaking the IsDevelopment function logic - asp.net-core

With AspNet Core, I would like to have a different config value when I develop a web site on my local computer and when the web site is published on the development server.
For exemple, on my computer, the log files use the path "..\..\logs\app.log" and on the development server it's "w:\logs\app.log". Since that by default, AspNet Core is using the appsettings.Development.json file wherever I'm on my development computer or on the development server, I cannot set the path differently.
So how can I distinguish when the code run on my local computer and when it run on my development server and have a different settings in my appsettings.json files and still use env.IsDevelopment() that will return true on both environment? The reason I need that is because Microsoft use the IsDevelopment() function in there own logic and I don't want to break that.

.NET Core solves this problem by using "Environments".
It's kind of evolved over the versions so it's a little different depending on which version of .NET Core you are actually using. But in short, your code will typically load appsettings.json first, then overwrite any settings from a file called :
appsettings.{env.EnvironmentName}.json
Notice how the Environment is suffixed to your appSettings. To set the environment for your machine, if you are on Windows you can run a powershell command like :
$Env:ASPNETCORE_ENVIRONMENT = "Development"
Or have a quick google around "How to set environment variables". As long as the key is "ASPNETCORE_ENVIRONMENT", then whatever you set it to, you can then load that file as your settings.
More info : https://dotnetcoretutorials.com/2017/05/03/environments-asp-net-core/

From your description, I understood that you want to keep single Config file. If that is the case, you can alter your configuration setting on server side using environment variables.
Logging__logPath=C:\dir\file.log
this link may help you https://medium.com/thirddev/overriding-configuration-using-environmental-variables-in-asp-net-core-d38079475654
If your server is hosted on IIS then you can change your environment variables under Configuration Editor. Here is the step by step instructions
Go to your application in IIS and choose Configuration Editor.
Select Configuration Editor
Choose system.webServer/aspNetCore (RC2 and RTM) or system.webServer/httpPlatform (RC1) in Section combobox
Choose Applicationhost.config ... in From combobox.
Click on enviromentVariables element and open edit window.
Set your environment variables.
Close the window and click Apply. Done
REF: https://stackoverflow.com/a/36836533/1118978
Visal demonstration:
https://www.andrecarlucci.com/en/setting-environment-variables-for-asp-net-core-when-publishing-on-iis/
If you prefer to have multiple config files, then :
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
and environment variable is needed to be set ASPNETCORE_ENVIRONMENT=DevServer and your config file will be appsettings.DevServer.json

Related

How can appSettings.{environment}.json be loaded before environment is known? (AspNetCore)

According to microsoft blog the ASPNETCORE_ENVIRONMENT variable is loaded in order:
appsettings.json file
appsettings.{env.EnvironmentName}.json file
The local User Secrets File
Environment Variables
Command Line Arguments (or equivalently launchSettings.json)
and "The last key loaded wins".
Questions:
But how can the file appsettings.{env.EnvironmentName}.json be loaded before the final Environment is known?
Can it happen that I set 'Staging' environment through command-line and appSettings.Development.json is loaded because during step 2 it is not yet known?
There are two sets of configuration for an ASP.NET Core application:
The configuration for the WebHost.
The configuration for the application itself.
First the WebHost configuration is built (source):
_config = new ConfigurationBuilder()
.AddEnvironmentVariables(prefix: "ASPNETCORE_")
.Build();
As the source code shows, the configuration for the WebHost uses only environment variables and only those that are prefixed with ASPNETCORE_. One of those environment variables is, unsurprisingly, ASPNETCORE_ENVIRONMENT.
A little later down the line, an implementation of IHostingEnvironment is instantiated. This ends up using _config to retrieve a configuration setting named environment, which comes from the ASPNETCORE_ENVIRONMENT variable. If there is no such value, it defaults to Production.
Next up, the configuration for the application itself gets built. At step 2 in your question, the value of env.EnvironmentName is from the IHostingEnvironment I've already mentioned. If you were to set an environment value of e.g. Staging as a command-line argument, it would not change the value used in the WebHost configuration, as this applies only to the application configuration.
Andew Lock goes into more detail about how this all works and also demonstrates how to configure the WebHost to use additional configuration sources.

.NET Core 2.2 API on IIS returns error if it attempts to connect to Db but otherwise works fine

When I publish my .NET core app to a development IIS server, I make a call to the API and the method works fine locally. This method makes a Db call using a connection string stored in
appSettings.json as well as appSettings.Development.json
Observations:
- Yes, I have ASPNETCORE_ENVIRONMENT = Development and I have both an appSettings.json file AND appSettings.Development.json file
- So I started looking at the published files and I had BOTH of these json files in the published folder, even though appSettings.Development.json properties is set to "Build Action" = content and Copy to Output Directory = Do Not Copy
- If I comment out the code that his the Db, and return dummy data, and republish the api, i get the results fine with no complaints about "development mode"
Error I get when calling the API trying to hit the Db
Error.
An error occurred while processing your request.
Request ID:
0HLL1GOCEHH73:00000001
Development Mode
Swapping to the
Development environment displays detailed information about the error that occurred.
The Development environment shouldn't be enabled for deployed applications.
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the
Development environment by setting the
ASPNETCORE_ENVIRONMENT environment variable to
Development
and restarting the app.
Questions:
- The Db connection strings are in both
[ update ]
Brain-fart! The db connection strings were using 'trusted', so no wonder they worked locally! Once I put in the credentials, and re-published, things worked like I expected. However, the error message threw me off.
Im still not sure why I have both of those appSettings files published? Which one will it use?
I am assuming your appsetting files are named as following:
appSettings.json
appSettings.dev.json
typically, you have to explicitly set the environment to dev. if you use Visual Studio for development, it sets an environment variable that tells the application to put it in dev mode.
Without seeing the initializing logic, I would say in prod it will use the appSettings.json.
Take a look at this article, it explains configuration in more details.

How to isolate connectionStrings in separated file in asp.net core?

I am new to asp.net core and I am wondering how to put connectionStrings in separated file(json file) and ignore it so every developer can modify it to add his local connectionStrings?
In Asp.net I used to put connectionStrings in separated file (ex connectionStrings.config) and ignore it on git. Then inside web.config adding the following configuration:
<connectionStrings configSource="connectionStrings.config" />
So could you please guide me to how I can achieve that using asp.net core?
use a ConfigureAppConfiguration in your Program class
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureAppConfiguration(builder =>
{
builder.AddJsonFile("appsetting.json");
builder.AddXmlFile("connectionStrings.config"));
});
With .NET Core or ASP.NET Core we don't use web.configs or app.configs for that purpose anymore. There is a new configuration-system built by Microsoft. By default, the webhost builds a configuration that includes these in that order
appsettings.json, optional
appsettings.{environment}.json, optional
environment-variables
In your case you will want to build one manually.
For that you need to have a reference to (included by default for visual studio templates via meta-package)
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Json
Microsoft.Extensions.Configuration.EnvironmentVariables
Now instead of using the default configuration, build your own within your startup class.
public class Startup
{
// environment is being injected by the webhost
public Startup(IHostingEnvironment environment)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile(Path.Combine(AppContext.BaseDirectory, "appsettings.json"), optional: false) // u can change that if you want to be optional
.AddJsonFile(Path.Combine(AppContext.BaseDirectory, $"appsettings.{environment.environmentName}.json), optional: false)"
.AddJsonFile(Path.Combine(AppContext.BaseDirectory, "connectionsettings.json"), optional: false)
.Build();
}
}
Then you can go ahead and access them kinda like before
configuration.GetConnectionString("MyConnectionString");
and your json file must look like that
"ConnectionStrings": {
"MyConnectionString": "some-connectionstring-value"
}
You could also use .NET user secrets, see:
https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1&tabs=windows
These have huge benefits:
the secret file is outside git folder, so it will never be committed by mistake.
you can edit the secret file from Visual Studio and it looks similar to appsettings.json
Basically you have the secrets configuration only active for development (that is the default), and for production you would have another configuration source (Key vault or environment variable, etc)

Which values does WebHost read from appsettings.json

In .Net Core you can self host a web server using WebHost. There is a method called CreateDefaultBuilder(), to which the Microsoft documentation states the following:
CreateDefaultBuilder performs the following tasks:
Loads app configuration from:
appsettings.json.
However, there doesn't seem to be any documentation on which parameters you can put into appsettings.json to have the WebHost automatically get configuration values other than the default values.
For example, I tried adding the following to my appsettings.json, but the server is started with http://localhost:5000 regardless:
{
"Kestrel" : {
"urls" : "http://*:8080"
},
"server" : {
"urls" : "http://*:8080"
}
}
I know I can read appsettings.json myself using ConfigurationBuilder, but that sort of defeats the purpose of the documentation
So, what do I need to put into my appsettings.json file to have CreateDefaultBuilder() not use the default values? A list of all possible values to put into appsettings.json would be welcome as well.
Why does CreateDefaultBuilder not configure the host with appsettings.json values?
Part of the answer is to distinguish between host and app configuration. The documentation says that CreateDefaultBuilder...
Loads host configuration from:
Environment variables prefixed with ASPNETCORE_ ...
Command-line arguments.
Loads app configuration from:
appsettings.json.
appsettings.{Environment}.json.
From within CreateDefaultBuilder, the reason that appsettings.json does not automatically affect the host, is that those settings are configuring the app, and the app config does not affect the host config. The documentation indicates that when it says:
IWebHostBuilder configuration is added to the app's configuration, but the converse isn't true — ConfigureAppConfiguration doesn't affect the IWebHostBuilder configuration.
Looking at the source code shows that the CreateDefaultBuilder method only adds the appsettings.json values from within its call to ConfigureAppConfiguration. That is why those values are not automatically impacting the host.
How can we configure the host with values from a *.json file?
CreateDefaultBuilder does not automatically configure the host with a *.json file. We need to do that manually, and the documentation specifies how. In the example the file is named hostsettings.json, and the example adds it explicitly like this:
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("hostsettings.json")
.Build();
return WebHost.CreateDefaultBuilder(args)
// this impacts *both* host and app config
.UseConfiguration(config)
.UseStartup<Startup>();
There is no magic in the name hostsettings.json. In fact, we could combine our host settings and our app settings into one file named appsettings.json. The way CreateDefaultBuilder works encourages us to keep those settings somewhat separate.
What keys can we put in a *.json file to configure the host?
This is the list of keys that we can use to configure the host:
"applicationName"
"startupAssembly"
"hostingStartupAssemblies"
"hostingStartupExcludeAssemblies"
"detailedErrors"
"environment"
"webroot"
"captureStartupErrors"
"urls"
"contentRoot"
"preferHostingUrls"
"preventHostingStartup"
"suppressStatusMessages"
"shutdownTimeoutSeconds"

Unable To Bind To Other Port with UseUrls

The following code just won't change the port to 9874. It stays the same in Project -> Debug -> Web Server Settings -> App URL -> "http://localhost:56021/", which uses the 56021 port. I am using VS 2017 to create .net core webapi project.
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseUrls("http://localhost:9874")
.Build();
It is the same even i change to Release mode.
Solve it by changing launchSettings.json.
If the setting is set in the above file, then what is the point to have UseUrls as it always refer to launchsettings.json setting?
In Project -> Debug -> Web Server Settings you see is a project profile that is used only when you try to run app from VS.
And in VS this is the responsibility of launchSettings.json to store and retrieve project configuration settings needed to run a project from VS only. In other words, launchSettings.json is ignored if you run app outside of VS (let's say from command line for example).
And back to .UseUrls method: it doesn't (and cannot, mainly because your app doesn't know about profiles at all) change above project profiles. Yes, this method indicates the IP addresses or host addresses with ports and protocols that the server should listen on for requests. But those settings will be applied to the Server instance that will be created on app start.