Appsettings transform in .NetCore not working as expected - c#

I have developed a web API and published it on azurewebsites.net.
I have added the following additional appsettings:-
appsettings.Dev.json
appsettings.Test.json
appsettings.Prod.json
To be able to extract values from these appsettings transforms I made the following code changes:
Tried the solution mentioned here:
https://stackoverflow.com/a/44953524/10485667
Even tried using only the Development/Debug, Staging and Production/Release instead of Dev, Test, Prod receptively. But no luck. It would only publish the values from the main appsettings.json.
Startup.cs
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
#if DEBUG
.AddJsonFile($"appsettings.Dev.json", optional: true)
#endif
.AddEnvironmentVariables();
Configuration = builder.Build();
appSettings = Configuration.Get<AppSettingsModel>().AppSettings;
}
even tried this code:
AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
Tried changing the Program.cs:
public class Program
{
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.AddJsonFile($"appsettings.Development.json", optional: true)
.Build();
ILogger logger = null;
var host = CreateWebHostBuilder(args)
.UseConfiguration(config)
.Build();
logger = host.Services.GetService<ILogger>();
host.Run();
}
}
Tried every possible solution provided on internet but no luck. After publishing to azure, it takes the values only from appsettings.json
I think I might be making some conceptual mistake while attempting these solutions. Any kind of help is appreciated.
Thanks in advance

Related

How to get Args from Provider (c# .NET Core console app)?

I try to make a .NET Core console app with singleton. In main I have:
Configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddCommandLine(args)
.Build();
var services = ConfigureServices();
var serviceProvider = services.BuildServiceProvider();
serviceProvider.GetService<App>().Run();
and in App.cs:
public App(IConfiguration config, IConfigurationRoot configuration)
{
conf = config;
var list = configuration.Providers.ToList();
var provider = (CommandLineConfigurationProvider)list[1];
}
How can I download string[] (or list, or whatever) with arguments from provider?
Answer provided by Martin Costello (from comments):
You can use Environment.GetCommanLineArgs() to get the raw command line to the application. The providers are an abstraction, so don't give you access to exactly what was passed into them.
Link: learn.microsoft.com: GetCommandLineArgs

How to configure environment on webjobs sdk?

I have a dotnet console app using webjobs sdk and I´m not able to find how to get the configuration file correctly based on the environment. My code:
static void Main(string[] args)
{
var builder = new HostBuilder();
var environmentName = Environment.GetEnvironmentVariable("environment");
builder.ConfigureHostConfiguration(config =>
{
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
config.AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true);
config.AddEnvironmentVariables();
});
...
After that I create 2 files: appsettings.json and appsettings.Production.json. When I´m debugging, even with the variable set to production, I always get the appsettings.json values and not the appsettings.Production.json value. What Im doing wrong here?

ArgumentNullException for ConnectionString When trying to remotely connect to .net core API

First of all is this happening in a Mac and I'm new to dotnet core.
I have installed dockers and setup everything in dotnet core. I did add connectionstring to the 'appsettings' and 'appsettings(Development)'.
"ConnectionStrings": {
"Default": "server=localhost; database=Monitor; User ID=sa; Password=MyComplexpPassword!234;"
},
This is Program.cs file Main method
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
This is startup.cs class ConfigureServices method.
public void ConfigureServices(IServiceCollection services)
{
services.AddAutoMapper();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddDbContext<MonitorDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Default")));
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
services.AddScoped<IUserRepository,UserRepository>();
}
This is a Controller test method to test API.
[HttpGet("getUser")]
public UserResource GetUserInfo()
{
var user_1 = new User();
user_1.FirstName = "MAC";
user_1.LastName = "OS TEST";
user_1.Username = "Apple#gmail.com";
return mapper.Map<User, UserResource>(user_1);
}
This method will perfectly execute If I make a rest call(http) without setting up Program.cs class for remote access.
Now I have set it up to run in 'http://0.0.0.0:6001', So that I can access the API from my phone or from another pc in the same wifi.
I followed This instructions.
Now My Program.cs main method is like this.
public static void Main(string[] args)
{
// CreateWebHostBuilder(args).Build().Run();
var configuration = new ConfigurationBuilder()
.AddCommandLine(args)
.Build();
var hostUrl = configuration["hosturl"];
if (string.IsNullOrEmpty(hostUrl))
hostUrl = "http://0.0.0.0:6000";
var host = new WebHostBuilder()
.UseKestrel()
.UseUrls(hostUrl) // <!-- this
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseConfiguration(configuration)
.Build();
host.Run();
}
In terminal I ran this command dotnet run --hosturl http://0.0.0.0:6001
If try to access same method as before this happens.
Notice:- I changed only the host, Because I need to test the API with other devices.
I have other controllers and methods that are connecting to the database and do crud operations with it, Those API calls also face the same issue like this. This only happens if I set it up to remote access.
Notice:- If I change the Startup.cs class Connection string line like this, It will work flawlessly in both configurations.
services.AddDbContext<MonitorDbContext>(options => options.UseSqlServer("server=localhost; database=Monitor; User ID=sa; Password=MyComplexpPassword!234;"));
But I felt that this is not good practice. In future, I have to add JWT Authentication to the API so that APP_Secret also needed to add to the AppSettings.json file.
Thank you.
you didn't tell the application to use appsettings.json. change below configuration
var configuration = new ConfigurationBuilder()
.AddCommandLine(args)
.Build();
To
var configuration = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddCommandLine(args)
.Build();
As an alternative, you can use the static WebHost.CreateDefaultBuilder method which by default loads settings from 'appsettings.json', 'appsettings.[EnvironmentName].json', and command line args.
Note -> As stated here:
AddCommandLine has already been called by CreateDefaultBuilder. If you
need to provide app configuration and still be able to override that
configuration with command-line arguments, call the app's additional
providers in ConfigureAppConfiguration and call AddCommandLine last.
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
// Call other providers here and call AddCommandLine last.
config.AddCommandLine(args);
})
.UseStartup<Startup>();

AWS ElasticBeanstalk unable to read appsettings using ASPNETCORE_ENVIRONMENT in ASP.NET Core web app

Background & Attempted Fixes
I am attempting to automate my .NET Core web application deployment using AWS ElasticBeanstalk and configuring each environment with the ASPNETCORE_ENVIRONMENT variable.
I then found out that via numerous (one & two) Stackoverflow questions this is broken in ElasticBeanstalk.
Then following those two SO questions, I tried this in my Startup.cs:
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)
.AddJsonFile(#"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
var ebConfig = ParseEbConfig(Configuration);
builder.AddInMemoryCollection(ebConfig);
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.CreateLogger();
CurrentEnvironment = env;
}
public IConfigurationRoot Configuration { get; }
public IHostingEnvironment CurrentEnvironment { get; set; }
private static Dictionary<string, string> ParseEbConfig(IConfiguration config)
{
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (IConfigurationSection pair in config.GetSection("iis:env").GetChildren())
{
string[] keypair = pair.Value.Split(new[] { '=' }, 2);
dict.Add(keypair[0], keypair[1]);
}
return dict;
}
and tried accessing the new containerconfiguration values in my HomeController (to test this out) like this: _config.GetSection("ASPNETCORE_ENVIRONMENT").Value; where _config is IConfiguration. This worked when debugging locally & I was able to get the ASPNETCORE_ENVIRONMENT properly. But in Beanstalk it was unable to find that variable.
What seems to be going on
So it appears that Beanstalk is unable to access the containerconfiguration file and it certainly is not able to retrieve the ASPNETCORE_ENVIRONMENT variable, no matter where I set it in my configurations with Beanstalk.
What I am wondering
At the end of the day, I want to be able to set the ASPNETCORE_ENVIRONMENT variable to Dev (for example) in my Beanstalk configuration and have my .NET application load the appropriate appsettings.json file for the environment. I don't necessary need to go the route of the containerconfiguration file, but this seems to be the way it needs to be done.

asp.net core TestServer can't find configuration

I am creating some tests using TestServer which is bootstrap with a complex configuration as following:
var config = new ConfigurationBuilder()
.Build();
webHostBuilder = new WebHostBuilder()
.UseConfiguration(config)
.UseKestrel()
.CaptureStartupErrors(true)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<MockLicenseStartup>()
.UseEnvironment("Development")
.UseUrls("http://locahost");
testServer = new TestServer(webHostBuilder);
Both in my "asp.net core" project and in my test project I have created multiple appsettings.json which is used to provide things like:
Connection String
Log verbosity
Custom Sections
The issue I am facing is that my Configuration class, inside the MockLicenseStartup is not able to load any of the available appsettings.json.
The code used inside MockLicenseStartup.cs is this one:
public MockLicenseStartup(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();
}
When I call Configuration.GetConnectionString("") it throws an exception and if I inspect further I can see that no configuration has been loaded actually. Probably is a problem related to the relative/absolute path of .UseContentRoot(Directory.GetCurrentDirectory())
In Test Environment,
.SetBasePath(env.ContentRootPath)
env.ContentRootPath is different from production, it is set to the test project's bin directory if I remember correctly. So, it will not locate the appsettings.json file. unless you copy it there after build.
If you are projects folder structure does not change. you can just try to hard code the appsettings.json" path in these two lines to where these are located.
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true
if this works (it should), you can make it better by find the appsetting.json path in code.
Below is my own code which work in test environment.
var settingFilePath = getSettingFilePath(settingFileParentFolderName: "APIProject");
var builder = new ConfigurationBuilder()
.AddJsonFile(settingFilePath + _settingFileName, optional: true, reloadOnChange: true)
.AddJsonFile(settingFilePath + "appsettings.Development.json", optional: true);
var configuration = builder.Build();
getSettingFilePath() is just a function to locate the setting file path in the Startup Project folder.
Hope this help.

Categories

Resources