I want a simple static class that accesses the Configuration object. All the config info is already read in from the appsettings.json file in the Startup class. I just need an e
Here is a way to obtain the configuration values from a NET.Core page without having to reference these statically but then still being able to pass them to other static functions called from the non-static class.
At the top of your non-static class add this:
private readonly IConfiguration _configuration;
Then in the constructor function bring in the existing configuration as input to the function:
IConfiguration configuration
Then assign the configuration to your read only variable inside the constructor function:
_configuration = configuration;
Here is an example of what it should look like:
public class IndexModel : PageModel
{
private readonly IConfiguration _configuration;
public IndexModel(IConfiguration configuration)
{
_configuration = configuration;
}
}
After this you can reference the configuration in any function in the class by referencing _configuration and can even then pass this on to other static functions that you call from other classes:
public async Task OnGetAsync()
{
AnotherClass.SomeFunction(_configuration);
}
Then in the called static class I can make use of the configuration values:
public static string SomeFunction(IConfiguration configuration)
{
string SomeValue = configuration.GetSection("SomeSectionOfConfig")["SomeValue"];
}
I have a class that calls some stored procedures for viewing and amending data and passes parameter values from appsettings.json using this approach.
A slightly shorter version based on the same principle as above...
public Startup(IConfiguration configuration)
{
Configuration = configuration;
StaticConfig = configuration;
}
public static IConfiguration StaticConfig { get; private set; }
To use in another static class:
string connString = Startup.StaticConfig.GetConnectionString("DefaultConnection");
I just created below class:
/// <summary>
///
/// </summary>
public static class ConfigurationManager
{
/// <summary>
///
/// </summary>
public sealed class ConfigurationManagerAppSettings
{
/// <summary>
///
/// </summary>
internal ConfigurationManagerAppSettings() { }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string this[string key] => (TheConfiguration ?? throw new Exception("Set ConfigurationManager.TheConfiguration in Startup.cs")).GetSection($"AppSettings:{key}").Value;
}
/// <summary>
///
/// </summary>
public static IConfiguration? TheConfiguration { get; set; }
/// <summary>
///
/// </summary>
public static readonly ConfigurationManagerAppSettings AppSettings = new ConfigurationManagerAppSettings();
}
and below code:
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) {
ConfigurationManager.TheConfiguration = Configuration;
After much research, this works (in ASPNetCore 2.2) for accessing the appsettings.json config from a static class but for some reason appsettings.development.json no longer loads properly but it might be something else in my project messing that up. The reloadOnChange does work. As a bonus it also has IHostingEnvironment and IHttpContextAccessor. While this works, I have recently decided to switch back to a more DI approach to follow the paradigm shift as others have mentioned.
So here is one of many ways to access some DI stuff (including the configuration) in a static class:
AppServicesHelper.cs:
public static class AppServicesHelper
{
static IServiceProvider services = null;
/// <summary>
/// Provides static access to the framework's services provider
/// </summary>
public static IServiceProvider Services
{
get { return services; }
set
{
if (services != null)
{
throw new Exception("Can't set once a value has already been set.");
}
services = value;
}
}
/// <summary>
/// Provides static access to the current HttpContext
/// </summary>
public static HttpContext HttpContext_Current
{
get
{
IHttpContextAccessor httpContextAccessor = services.GetService(typeof(IHttpContextAccessor)) as IHttpContextAccessor;
return httpContextAccessor?.HttpContext;
}
}
public static IHostingEnvironment HostingEnvironment
{
get
{
return services.GetService(typeof(IHostingEnvironment)) as IHostingEnvironment;
}
}
/// <summary>
/// Configuration settings from appsetting.json.
/// </summary>
public static MyAppSettings Config
{
get
{
//This works to get file changes.
var s = services.GetService(typeof(IOptionsMonitor<MyAppSettings>)) as IOptionsMonitor<MyAppSettings>;
MyAppSettings config = s.CurrentValue;
return config;
}
}
}
}
Startup.cs:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddHttpContextAccessor();//For HttpContext.
// Register the IOptions object
services.Configure<MyAppSettings>(Configuration.GetSection(nameof(MyAppSettings)));
//Explicitly register the settings object by delegating to the IOptions object so that it can be accessed globally via AppServicesHelper.
services.AddSingleton(resolver => resolver.GetRequiredService<IOptionsMonitor<MyAppSettings>>().CurrentValue);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//...
AppServicesHelper.Services = app.ApplicationServices;
//...
}
Controller:
public class MyController: Controller
{
public MyController()
{
}
public MyAppSettings Config => AppServicesHelper.Config;
public async Task<IActionResult> doSomething()
{
testModel tm = await myService.GetModel(Config.Setting_1);
return View(tm);
}
}
Another class library:
public static class MyLibraryClass
{
public static string GetMySetting_ => AppServicesHelper.Config.Setting_1;
public static bool IsDev => AppServicesHelper.HostingEnvironment.IsDevelopment();
}
MyAppSettings.cs is any class that maps to a MyAppSettings section in appsettings.json:
public class MyAppSettings
{
public string Setting_1 {get;set;}
}
appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"MyAppSettings": {
"Setting_1": "something"
}
}
Try avoid using a static class and use DI
namespace MyNamespace {
public interface IConfig {
string Username { get; }
string Password { get; }
}
public class Config : IConfig {
public Config(IConfiguration configuration) {
_configuration = configuration;
}
readonly IConfiguration _configuration;
public string Username => _configuration["Username"];
public string Password => _configuration["Password"];
}
}
The setup DI in StartUp class
public class Startup {
public void ConfigureServices(IServiceCollection services) {
//...
services.AddTransient<IConfig, Config>();
...
}
}
And use it like so
public class TestUsage {
public TestUsage(IConfig config) {
_config = config;
}
readonly IConfig _config;
public string Username => _config.Username;
public string Password => _config.Password;
}
This has already been said but I'm going to say it.
I believe .Net Core wants developers to get values through Dependency Inject. This is what I've noticed from my research but I am also speculating a bit. As developers, we need to follow this paradigm shift in order to use .Net Core well.
The Options Pattern is a good alternative to the static config. In your case, it'll look like this:
appsettings.json
{
"Username": "MyUsername",
"Password": "Password1234"
}
SystemUser.cs
public class SystemUser
{
public string Username { get; set; } = "";
public string Password { get; set; } = "";
}
Startup.cs
services.Configure<SystemUser>(Configuration);
And to use the SystemUser class, we do the following.
TestController.cs
public class TestController : Controller
{
private readonly SystemUser systemUser;
public TestController(IOptionsMonitor<SystemUser> systemUserOptions)
{
this.systemUser = systemUserOptions.CurrentValue;
}
public void SomeMethod()
{
var username = this.systemUser.Username; // "MyUsername"
var password = this.systemUser.Password; // "Password1234"
}
}
Even though we are not using a static class, I think this is the best alternative that fits your needs. Otherwise, you might have to use a static property inside the Startup class which is a scary solution imo.