Override appsettings.json Array With Env Variable - c#

I have this array in my appsettings.json:
"ServiceDefinitions": [
{
"Name": "encryption-api",
"Url": "http://localhost:5032",
"ApiKey": "",
"ExposedEndpoints": [
"encrypt",
"decrypt"
]
}
],
I want to be able to override this with an environment variable. I've added the env vars to the configuration builder like this, which seems to work for other values:
builder.Configuration.AddEnvironmentVariables();
And then I've attempted to set this in my Docker Compose file with:
environment:
- ASPNETCORE_URLS=http://gateway:8080/
- ServiceDefinitions="{\"Name\":\"encryption-api\",\"Url\":\"http://encryption-api:80\",\"ApiKey\":\"\",\"ExposedEndpoints\":[\"encrypt\",\"decrypt\"]}"
However, it's still picking up the value from the json file rather than the env var. I've also tried setting it inside [] but that makes no difference.
How can I do this?

Microsoft docs regarding app configuration.
You are going to want to make sure that your Json provider is registered before your environment variables provider. Then you'll want to setup your environment variables in your Docker file as follows:
environment:
- ASPNETCORE_URLS=http://gateway:8080/
- ServiceDefinitions__0__Name="encryption-api"
- ServiceDefinitions__0__Url="http://encryption-api:80"
- ServiceDefinitions__0__ApiKey=""
- ServiceDefinitions__0__ExposedEndpoints__0="encrypt"
- ServiceDefinitions__0__ExposedEndpoints__1="decrypt"

Related

cannot read values for few keys from local.settings.json file

I am unable to read the few of the keys from local.settings.json file. Below is the file content.
{
"IsEncrypted": false,
"Values": {
"KeyVaultUrl": "https://mykeyvault.azure.net/",
"SecretKey": "myconnectionstring",
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
I used the below code to read these values
var keyVaultUrl = Environment.GetEnvironmentVariable("KeyVaultUrl"); // returns null
var secretKey = Environment.GetEnvironmentVariable("SecretKey"); // returns null
var sample = Environment.GetEnvironmentVariable("AzureWebJobsStorage"); // returns "UseDevelopmentStorage=true"
I am not sure why it returns null for the key I have added. I have set Copy Always in Copy to Output Directory and Build Action to None.
Please assist.
Values you are trying to read, are not written in environment variables. To use config files, use IConfiguration. It can contain environment variables, multiple config files and much more.
It depends on type of your application, if you are using simple console application without hosts and builders, use this, but if you are using some kind of framework use this approach.
An environment variable is a variable whose value is set outside the program, typically through functionality built into the operating system!
Your data in appsettings is just key-value pairs of configuration settings for your application (from it's name - appsettings).
To access data in your appsettings you need to inject IConfiguration to your service (or controller or whatever)
private readonly IConfiguration _configuration;
public ServiceConstructor(public IConfiguration)
=> _configuration = configuration;
and then you can read values from there like this:
_configuration["IsEncrypted"]
and
_configuration["Values:KeyVaultUrl"]

asp.net core override connection strings via ENV variables

I have an asp.net core API 2.2 implemented. I have created a docker image. I would like to override connection strings in appsettings.json file.
Is there any way to do it? I tried via environment variables when I start the container with command docker container run -e "ConnectionStrings:DefaultConnection={...here goes the connection string}"
I have also builder.AddEnvironmentVariables(); in my Startup.cs but connection string in my appsetting.json is not replaced.
I checked it inside the container, appsetting.json is there but the values are not replaced.
Any other way how to do such cases? Thx.
For -e, it will override the system environment which will change the connectionstring when you retrive from code, it will not affect the content in appsettings.json.
For example
Assume you have a appsettings.json like
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-TestDockerConfiguration-416C6FD2-3531-42D6-9EDE-18AC45901208;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
Retrive the connectionstring by _configuration.GetConnectionString("DefaultConnection") like
public class HomeController : Controller
{
private readonly IConfiguration _configuration;
public HomeController(IConfiguration configuration)
{
_configuration = configuration;
}
public IActionResult Index()
{
return Ok(_configuration.GetConnectionString("DefaultConnection"));
//return View();
}
}
For docker run -it -p 8888:80 dockerconfiguration, it will return "Server=(localdb)\\mssqllocaldb;Database=aspnet-TestDockerConfiguration-416C6FD2-3531-42D6-9EDE-18AC45901208;Trusted_Connection=True;MultipleActiveResultSets=true" for Index Action
For docker run -it -p 8888:80 dockerconfiguration -e "ConnectionStrings:DefaultConnection"="testsqlstring", it will return testsqlstring
So, if you only want to override the value in appsettings.json during runtime, you just need to specify like Step 4
If you prefer change the appsettings.json file in docker container, you could follow steps below
Install vi command with apt-get install vim -y
Run docker exec -it 43ea835776dd /bin/bash to go into container
Run ls to list files and find the appsettings.json
Run vi appsettings.json to modify the content
Run cat appsettings.json to check the content whether it is changed
Run exit and access the Home/Index to check the result.
appsetting.json never gets changed, however based on the hierarchy, variables values get overridden. Take a look at the examples at https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.2#conventions . It works pretty well. Perhaps just to be sure that you didn't break something because of command line execution, you can try to assign environment variables via docker-compose. The rule of thumb is that the pattern that you use for the "key" must match (with the help of __ instead of :)what you have in the json file, so that it gets overridden.
Tried without the quotes for the ConnectionStrings section and it worked (on a PowerShell console.
docker run -d -p 8080:80 --name letscosmosweb -e ConnectionStrings__ProductsDbContext=$key letscosmosweb:v1
$key variable contains the connection string
If you're using docker-compose
Besides specifying the variable in .env, don't forget to also set it in environments section of the docker-compose.yml. It got me :)

What does "Using" in Serilog JSON configuration do?

What does actually Using do in Serilog JSON configuration (e.g. in AppSettings.json file in .Net Core environment)?
Let us take this configuration for example:
"Serilog": {
"Using": [ "Serilog.Sinks.Console" ], <=======***HERE***=========
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{
"Name": "RollingFile",
"Args": {
"pathFormat": "logs\\log-{Date}.txt",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "My Application"
}
}
In the example above we used File sink WITHOUT adding it to Using attribute. However, everything seems to be working ok.
So I cannot understand exactly why we basically need this Using. Could someone explain it to me please?
This is covered in the documentation for Serilog.Settings.Configuration:
(This package implements a convention using DependencyContext to find any package with Serilog anywhere in the name and pulls configuration methods from it, so the Using example above is redundant.)
This means that it's used to define which packages are used for locating Serilog sinks, but it's redundant when using the Serilog.Settings.Configuration package.
More Information
I've had a look at the Serilog source code in order to be able to provide more information on exactly what Using does and why it might be needed in the first place. I hope the following explanation is helpful.
Consider the following code-based setup:
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateLogger();
In this example, Console is an extension method for LoggerSinkConfiguration (and so it takes, as its first parameter, an instance of LoggerSinkConfiguration). When using this code-based approach, the code will only compile if this extension method can be found within a referenced assembly.
Next, consider the following approach, which uses the IConfiguration-based approach:
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(someConfiguration)
.CreateLogger();
{
"Serilog": {
"Using": ["Serilog.Sinks.Console"], // Redundant.
"WriteTo": ["Console"]
}
}
In this example, the compilation process has no knowledge of what the JSON string value "Console" refers to and so there's a need for a process that can go from the string "Console" to the Console() extension method mentioned above. In order to do that, Serilog needs to first find the extension method at runtime (which, in this example, lives in the Serilog.Sinks.Console assembly).
This finding process is done using reflection, which does a bit of assembly scanning to find public static methods that take as their first parameter a LoggerSinkConfiguration. The Using directive you've asked about in your question is a mechanism for helping determine exactly which assemblies should be scanned when looking for these extension methods.
As the documentation states, the IConfiguration-based approach uses DependencyContext in order to automatically scan assemblies that have Serilog in their name. Because Serilog.Sinks.Console does have Serilog in its name, there's no need to add this to the Using directive. You also have the option to provide your own DependencyContext instance when using this approach and so you might then need to be explicit about which assemblies to scan when looking for sinks.

Config value interpolation using Circle CI?

I am attempting to interpolate API username and password into my appsettings.json using Circle CI. I have placeholder values "ApiUsernamePlaceholder" and "ApiPasswordPlaceholder" that correspond to "Username" and "Password" fields in the json, like so:
"API": {
"URL": "https://some.url.com/api",
"username": "ApiUsernamePlaceholder",
"password": "ApiPasswordPlaceholder"
}
Is it possible, using Circle CI, to substitute the placeholders with an actual value at runtime? I have found conflicting statements on the issue, and the documentation is not clear.
This is a .Net Core 2.0 C# API project.
Yes. Like on any Unix-based environment, during your build use sed to swap out the place holders for the value of private environment variables that you'd set via the CircleCI webapp.

Azure Functions how to add application settings to bindings

I'm trying to add some custom binding using my app settings for my Azure Function. I need to receive only string a string from my settings.
I would like to get simpleValue from my settings.
{
"bindings": [
{
"name": "someValue",
"type": "stringSetting",
"connection": "simpleValue",
"direction": "in"
}
],
"disabled": false
}
and the get it in Run method:
static void GetOrders(TraceWriter log, string someValue)
{
log.Info(someValue);
}
Is it even possible. Maybe there is other way to do it?
I already found the solution. Just add:
using System.Configuration;
and add this line to code with the key ("simpleValue") value:
ConfigurationManager.AppSettings["simpleValue"]
App Settings configurations can be referred in binding json as %MY_CUSTOM_CONFIG% - enclosed within percent symbols.
Note that the connection property of triggers and bindings is a
special case and automatically resolves values as app settings,
without percent signs.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings

Categories