Fallback appsettings.json in asp.net core application - c#

I've an Asp.Net Core application.
When we first launch it, the code check for some variable in it, and if missing, it displays a wizard, which allow our users to configure some stuff. Those configured element are then stored in this appsettings.json(could be SMTP settings, mongo db settings, ...) and the app is restarted to take those into account.
This part work fine. The issue is that this file gets commited by every developer on every change, and some things are referencing things that are local(could be the schema version of our database, or some folder). We tried to put this file in the git ignore list, but since there are some settings(like log level) that are present(and should stay present), the file needs to be presents and its updates are tracked.
So I'm wondering: Is there a way to have some sort of "template" of appsettings.json, like initial.appsettings.json, and when the Asp.Net Core app starts, check if the file is missing, copy it and restart if needed?
Like this we can have this initial.appsettings.json being tracked, and ignore the appsettings.json in our git repository?

After test, the coon value will be overriden by the settings in connectionstrings.json file. You can find it below.
Splitting the files in appsettings.json is a good option for your current situation.
You can divide the configuration in the appsettings.json file into connectionstrings.json, and logging.json according to your requirements.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile("connectionstrings.json", optional: true, reloadOnChange: true)
.AddJsonFile("logging.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
Load it at startup with the following code. Then you are ignoring which specific files according to your needs.

Related

How can I use EF Core without appsettings.json

I need to use the dotnet ef tools utility, but I need to set a connection string in appsettings.json.
I don't want to store it in appsettings.json, because project is stored in the git repository.
At the moment, I keep launchSettings.json in the EnvironmentVariables section, but this does not help me because dotnet ef tools simply does not see these values. I tried to implement IDesignTimeDbContextFactory but everything is the same. He just doesn't see these values.
I found a solution that requires you to explicitly enter the value of the connection string, but this option also does not work.
The thing is that you should not store any secret value in git/repository at all.
Ideally this connnection string should be in a vault/Secret place which you will have access using another password, so eventually you need to "store" a password somewhere.
There is differnt approaches for this, as mention the most common one will be something like _secret.GetConnectionString() -> this calls to another service which will return the connectionstring.
Other solution you can do (probably better in your case) is to "setup" a default/plain appsettings.json just store the value like connection: xxxxxx and then use environment variables to replace that value. The configuration builder is already built with this in mind.
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables() //This line here
.Build();
Then you can just set up the value in your own machine.
For deploying to production it will depends which software you use to deploy the app, but it will have some way to allow you to add environment variables.
Finally, as an extension of the previous code you can add your "own" json
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile("appsettings.private.json")
.Build();
So doing this, in appsettings.private.json you will only need to write the connectionstring property. You will not need to write the entire document.
and then you can just add a rule on .gitignore to ignore it.

Azure functions - getting configuration recommended practices

I have created an Azure Function v2. In most articles I people suggest following:
var config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
Does a function hosted on azure also have a local.settings.json file? Will this code snippet get the app settings defined in Azure? Or do you need to change local.settings.json before publish? I thought local.settings.json was a local developer thing?
Is there any recommended practices using above snippet vs
Environment.GetEnvironmentVariable("xx")?
The first way you posted works just fine, both locally and in the cloud.
Note: In Azure, there is no local.settings.json (or should never be). This is only being used when debugging locally. There it is being picked up by the Functions runtime the same way it picks up AppSettings when running in Azure - and the settings are injected into your app as env variables. I have been using this for most of the time.
However, I recently started to switch to the second way, using Environment variables (Environment.GetEnvironmentVariable("xx")). Why? Simply because it is shorter and requires not extra usings etc. Apart from that there is no difference that I am aware of in using either of those ways.

How to update a single value in Application settings at runtime in Azure Function App

I'm building my first Function App so if I'm asking a silly question, please keep that in mind :)
I have a need to store some settings at runtime.
In standard desktop apps I can easily update app.config
by using:
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["UserId"].Value = "myUserId";
config.Save(ConfigurationSaveMode.Modified);
but in Function App I load config using ConfigurationBuilder:
var config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
and there is no way to update that config object.
When developing locally I can update local.settings.json, but when running on Azure everything is loaded from Application settings (Environment variables).
My question is: how can I update a single value in Application settings that are associated with my Function App?
I found a similar question but the solution there requires registering app in AAD and it is updating all settings, not just one value.
Take a look at the appsettings.json based approach.
Note that in-built support for appsettings.json files is not supported in Azure functions (yet). There is a github issue that tracks this.
There are few ways to do things at present. An example answer here:
Azure Functions, how to have multiple .json config files
There is also a similar solution described at github:
https://github.com/Azure/azure-functions-host/issues/4464#issuecomment-494367524

TestServer to use real sql database

I'm creating integration tests for ASP.NET Core WebAPI. I'm trying to make TestServer to use real, NOT in memory, sql-server database.
The first problem was, that WebHostBuilder didn't see connection string in "connectionstring.json", so I moved connection string cofnig to "appsettings.json". Now WebHostBuilder loads the connection string from appsettings.json file, but it doesn't load any data from sql-server database when executing a query (returns empty collection). It does, when I run it normally (not as testserver) and do GET through Postman.
My question is: "Is it possible to make TestServer to use sql-server database and how to do it?"
I found a similar question here call api Test server : .net core API integration tests , but there is no answer how to make TestSever works with sql-server database.
TestServer:
_server = new TestServer(WebHost.CreateDefaultBuilder()
.UseEnvironment("Development")
.ConfigureAppConfiguration(AddConfigFiles)
.UseStartup<Startup>()
);
AddConfigFiles method:
public static void AddConfigFiles(WebHostBuilderContext hostingContext, IConfigurationBuilder config)
{
var env = hostingContext.HostingEnvironment;
config
.AddJsonFile("connectionstrings.json", optional: true)
.AddJsonFile($"connectionstrings.{env.EnvironmentName}.json", optional: true)
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
config.AddEnvironmentVariables();
}
Connection string
"Data Source={MyServerName};Initial Catalog={MyDatabaseName};Integrated Security=True;"
Yes it is possible, if you want to see a full setup look at this answer: https://stackoverflow.com/a/54858071/2482439
In the example, the database used is SQLite but you can change the DatabaseType configuration to use SQL Server or any other.
Remember that the configuration files must be in the folder of the test project that are currently executing the tests, the scope, the path is defined by that.
So if you have Project.Integration.Tests, in the root folder you need to have connectionstrings.Development.json and appsettings.Development.json.
Also, you should probably set required true, for those config you really need.

.NET Core Web API not reading environment correctly

I have a .NET Core 2.0 Web API that is failing to read the environment specific app.settings file. As far as I can tell I have followed all the relevant steps.
This is my Startup.cs constructor:
public Startup(IHostingEnvironment env)
{
var config = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
}
I then have an appsettings.json file structure of:
appsettings.json
-appsettings.debug.json
-appsettings.release.json
-appsettings.production.json
And on the server where my API is deployed to I have a system environment variable key/value pair of
Variable = ASPNETCORE_ENVIRONMENT Value = Release
But when I make calls into the API the appsettings.production.json values are used, which (from what I understand) is the default when an environment variable of ASPNETCORE_ENVIRONMENT is not found.
Thoughts on what my setup might be missing to cause this default behavior?
You haven't specified, but I'm assuming your running in IIS. If that's the case, you need to edit the advanced properties of your App Pool and set the "Load User Profile" option to true. Otherwise, it won't actually read from your environment variables.

Categories