157

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 easy way to access it. Is this possible?

namespace MyNamespace
{
    public static class Config
    {
        public string Username => Configuration["Username"];
        public string Password => Configuration["Password"];
    }
}

Anywhere else in the app:

string username = Config.Username;
string password = Config.Password;
7
  • 2
    Consider using dependency inversion as apposed to service locator anti-pattern Commented Aug 25, 2017 at 16:20
  • By configuration you mean appsettings.json or app.config? Commented Aug 25, 2017 at 16:26
  • 1
    Using static class may be bad practice for unit testing: stackoverflow.com/a/38107134/2803565 Commented Dec 1, 2018 at 9:47
  • 3
    why a static class? you can directly inject configuration or create a singleton Commented Jan 7, 2019 at 19:11
  • 1
    @Jurion the two fields mentioned here are already stored in an injectable service. Anywhere in the app you would use them, you should be able to inject them. I don't see where RSA key comes as an example in this context. Commented May 23, 2022 at 0:02

20 Answers 20

122

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");
Sign up to request clarification or add additional context in comments.

5 Comments

share this configuration values among different class libraries will be tricky. Imagine you have infrastructure crosscutting sharing config / settings among several projects?
I am confused why this is not the accepted answer. Is there some risk to this? Looks simple and functional.
Because it's an anti-pattern. You should be able to inject all of the things a thing needs so you can substitute them during testing. When it's a static property with a private setter, how are you going to substitute that? You'll have to make it public just for testing, which is not right.
I don't feel it's an anti-pattern because IConfiguration has bind methods which allow you to bind it to a class for this reason and more. I wouldn't store it as IConfiguration though. Repeatedly parsing strings into their real types like booleans and ints is an anti-pattern I'm more concerned with in the microservice world. You don't have to set "StaticConfig" when you're changing values for testing. You can set MyConfigObject.MyProperty = 5 easily in your test setup and keep moving.
I believe this solution works as long as you do not use separate projects in your solution. usually, I create at least 3 projects in the solution controller project, service project, and repo project And I add a reference of the service project to the controller project to use services in the control layer. Based on this I can not add a reference of the controller project to the service project to use Startup.StaticConfig in-service project. it makes a circular dependency
66
  1. create the ConfigurationHelper static class in the service layer, so it can be used in other layers without circular dependency.
public static class ConfigurationHelper
    {
        public static IConfiguration config;
        public static void Initialize(IConfiguration Configuration)
        {
            config = Configuration;
        }
    }
  1. initialize the ConfigurationHelper inside the ConfigureServices method in the Startup class.
ConfigurationHelper.Initialize(Configuration);
  1. Use it wherever you want including your static classes
e.g: ConfigurationHelper.config.GetSection("AWS:Accesskey").Value;

8 Comments

This is the perfect solution for ASP.NET Core 3.1+. I tested it on .NET 5 and worked very good. Thanks for sharing it @pedram
you saved my time .net 6 in program.cs ConfigurationHelper.Initialize(builder.Configuration);
It worked perfectly fine .core 5.0 as well.
Working fine on .net core 7.0 preview version too.
Good Solution and working fine. I used it in static methods in .Net 8.0. Thanks a lot.
|
20

I've similar problems, and after reading the document from Microsoft. I've resolved it:

  1. Create an static ApplicationSettings class
public static class ApplicationSettings
{
    public const string User = "UserOptions";

    public static UserOptions UserOptions { get; set; } = new UserOptions();

    // other options here...
}
  1. Create an options class
public class UserOptions
{
    public string Username { get; set; };

    public string Password { get; set; };
}
  1. Init the Options class in Program.cs
ConfigurationManager configuration = builder.Configuration;

configuration.GetSection(ApplicationSettings.User).Bind(ApplicationSettings.UserOptions);
  1. Update your appsettings.json
{
  "UserOptions": {
    "Username": "input_your_username_here",
    "Password": "input_your_password_here"
  }
}
  1. You can call it anywhere in your project now
public void MethodA() 
{
    string username = ApplicationSettings.UserOptions.Username;
    string password = ApplicationSettings.UserOptions.Password;
}

public static void MethodB() 
{
    string username = ApplicationSettings.UserOptions.Username;
    string password = ApplicationSettings.UserOptions.Password;
}

Hope this could help you well.

3 Comments

ConfigurationManager is ambiguous
Then, I think you should recheck your package reference
It would be a more complete answer if you specified exactly which library you are referencing.
18

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"
   }
 }

3 Comments

Thank you @Soenhay for sharing a good solution. I also faced the same issue and resolved the issue following your approach.
I also need something similar for passing repository reference from static class. Can you suggest something @Soenhay ???
@NadimHossainSonet It might be better to ask it as a separate question for a more complete response. A quick summary is: you can use the same technique as above. Create a service class and interface for accessing the repository, register the service in ConfigureServices, and access it in the static class via services.GetService. Also, it seems pretty rare that I can't find a DI approach so you might revisit that.
13

I agree with mcbowes, it's in the docs, but the first example looks more like what you need...want:

public class Program
{
    public static IConfigurationRoot Configuration { get; set; }
    public static void Main(string[] args = null)
    {
        var builder = new ConfigurationBuilder()
             .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json");

        Configuration = builder.Build();

        Console.WriteLine($"option1 = {Configuration["option1"]}");

        // Edit:
        IServiceCollection services = new ServiceCollection();
        services.AddOptions();
        services.Configure<HelloWorldOptions>(_configuration.GetSection("HelloWorld"));
        // And so on...
    }
}

3 Comments

Yeah, but how do you access this instance of Configuration from another internal static class without having to rebuild it each time?
Then you should use the Options pattern.
@Tubbe Could you provide an example on how that works then? From what I've read in that article you'd still need to provide the options in the constructor, which isn't possible in a static class.
8

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;
  }

4 Comments

If you are migrating a NET Framework to NET Core, you must modify ALL classes that use application settings in order to inject configuration values (IOptions, IConfiguration or whatever). If you have a huge project, editing classes will take a lot of time and testing. :-O Would love to see an easier way without DI and modifying classes constructors
Why is it so bad to have a static class? I know dictionary access is fast, but it irks me just a little to have to use if(configuration["enabled"] == "True") or if(configuration.GetValue<int>("enabled")) when I feel like if(MyStaticClass.Enabled) is faster and lighter for methods which are called many times a second.
^ Completely agree. This approach (scroll down to "static instance") is still favored by many devs: weblog.west-wind.com/posts/2017/dec/12/…
try AppDomain.CurrentDomain.AssemblyResolve static event, look up dll paths by setting file path definition
7

You can use Signleton pattern to access your configurations from anywhere

    public class ConnectionStrings
    {
        private ConnectionStrings()
        {
        }
        // property with getter only will not work.
        public static ConnectionStrings Instance { get; protected set; } = new ConnectionStrings();

        public string DatabaseConnection { get; set; }
    }

and in your startup class

    public class Startup
    {
        private readonly IConfiguration configuration;

        public Startup(IConfiguration configuration)
        {
            this.configuration = configuration;
            configuration.GetSection("ConnectionStrings").Bind(ConnectionStrings.Instance);
        }

        public void ConfigureServices(IServiceCollection services)
        {
        }

        public void Configure(IApplicationBuilder app)
        {
        }
    }

4 Comments

Very good example. Can you show how to retrieve the values from appsettings.json and how it can be used in SomeController.cs
just like connection strings, define another singleton class call it AppSettings and bind a specific section to your singleton class and finally call it from anywhere but please aware that any modification in appsettings.json will not affect your singleton class until you restart the application ...
Cool thank you--I definitely prefer going the whole dependency injected route, but while incrementally migrating an older project this will help me move in that direction!
The question refers to static class, not non-static one.
5

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.

3 Comments

Static classes are not a best practice of Object Oriented Programming is a bit heavy handed. You mean to say stateful static classes. But even that is pretty heavy handed. DI in this form is arguably more of a component-design concept than a OOP one. Callers having to have knowledge of internal dependencies isn't really in the spirit of the OOP ideal. The trade-off developers love it for is granular unit testing. Many of us have extremely anemic OOP design that is closer to imperative functions passing around state than OOP.
how will i use options pattern if I am depending upon a library like mass transit and while configuring Bus, i want to use options pattern instead of accessing hard coded string from appsettings ?
how do you workaround for AppDomain.CurrentDomain.AssemblyResolve static event
3

Personally I like the method used in this link

Essentially it just adding a static field to your options class.

 public class WeblogConfiguration
 {
    public static WeblogConfiguration Current;

    public WeblogConfiguration()
    {
        Current = this;
    }
} 

Then in any static class you can do:

WeblogConfiguration.Current

Simple and very straight forward

Comments

3

A simple solution to access Configuration in static class is by using this beautiful line of code.

public static string value = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build().GetSection("Admin").Value;

Any place where you want to access Configuration without injecting it into the constructor use above mentioned piece of code. Hope it will be useful for someone out there.

2 Comments

Any values overwritten in appsettings.{Environment}.json will not be applied using this approach
Right, because you assign the value to a static variable, which requires reload the applicaton.
2

//Best way to read config values once and use it entire application in .Net Core 7 //config helper class added along with initialization

public class ConfigurationHelper
{
    public static IServiceCollection AddConfigServices(this IServiceCollection services, IConfiguration configuration)
    {
        ConfigurationHelper.Initialize(configuration);
        return services;
    }
    public static void Initialize(IConfiguration configuration)
    {
        SampleConfigVal = configuration["SampleConfigVal"];
        //SampleConfigVal holds value is "Demo of read config values in .net core"
        //we can access anywhere in the application still it's static
        
    }  
    public static string SampleConfigVal { get; set; }
}

// in program.cs file just included configuration initilization

var builder = new HostBuilder()
.ConfigureFunctionsWorkerDefaults();
IConfiguration configuration = default;
builder.ConfigureServices((context, options) =>
{
    configuration = context.Configuration;
});
////add service dependencies
builder.ConfigureServices(option =>
{

    //before start application it will initialize configurations
    option.AddConfigServices(configuration);   

});
var app = builder.Build();
app.Run();

//App seetings json just include key and values

   "Values": {
"SampleConfigVal": "Demo of read config values in .net core "
}

Comments

1

If you are using environment variables as your configuration, you can access the environment variable directly rather than via the configuration object.

using System;

namespace My.Example
{
    public static class GetPaths
    {
        private static readonly string MyPATH = 
            Environment.GetEnvironmentVariable("PATH");

        private static readonly string MySpecialPath =
            Environment.GetEnvironmentVariable("PREFIX_SpecialPath");
        ...
    }
}

Comments

1

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 is my 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;

Comments

0

I think you could use extension function, something like this

public static string ConfigToSomeThing(this IConfiguration config, int value)
        {
            return config[value.ToString()] ?? "";
        }

Then any place , just injection IConfiguration and use extension method

_systemConfiguration.ConfigToSomeThing(123);

Comments

0

I've used this approach and it seems to work well. In your static class, add a public IConfiguration property.

namespace MyNamespace
{
    public static class Config
    {
        public static IConfiguration Configuration { get; set; }

        public string Username => Configuration["Username"];
        public string Password => Configuration["Password"];
    }
}

In Startup.cs constructor, use dependency injection to get the configuration, and then assign it to the public member of your static class.

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        MyNamespace.Config.Configuration = configuration;
    }

    // The rest of the startup code...
}

Comments

0

I was getting same issue and I wanted to access app setting in static class so I put this solution. Write this below code in static class in my code class name was EncryptionUtility

private static string _saltKey = string.Empty;
private static IConfiguration configuration;

public static void AppSettingsConfigure(IConfiguration _config)
{
     configuration = _config;
     _saltKey = Convert.ToString(configuration["Security:EncyptPassword"]);
}

Call Appsettingconfiure from the program.cs file. Here, EncryptionUtility is static class or you can only write static method as your requirement. I had put this line above app.Run();

EncryptionUtility.AppSettingsConfigure(app.Services.GetRequiredService<IConfiguration>());

appsettings.json :

{
"Security": {
    "EncyptPassword": "Password"
  }
}

Comments

0

The static class is not a good practice in OOP. But the extension classes are exceptions.

If you are getting configuration from the host extensions, you can do something like the following:

    public static void AddWecomIdentityProvider(this WebApplicationBuilder builder)
    {
        var clientId = builder.Configuration.GetSection("ExternalIdPs:WeCom:ClientId").Value;
        var clientSecret = builder.Configuration.GetSection("ExternalIdPs:WeCom:ClientSecret").Value;
        var agentId = builder.Configuration.GetSection("ExternalIdPs:WeCom:AgentId").Value;

        if (string.IsNullOrWhiteSpace(clientId) || string.IsNullOrWhiteSpace(clientSecret) ||
            string.IsNullOrWhiteSpace(agentId))
        {
            return;
        }
        ...
    }

Comments

-3

Consider using the instructions here for ASP.NET Core Configuration.

You can create a class to store your configuration settings and then access the values, something like this:

_config.UserName

In Startup - ConfigureServices:

services.Configure<Config>(Configuration.GetSections("General"));

Then just inject your object wherever you need as:

IOptions<Config> config

4 Comments

How are you going to inject the object in a static class?
You inject the config into an instance rather than using a static class. Nowhere did I recommend attempting to inject the config into a static.
This question is specifically about using it in a static class
@SerjSagan Even though the question asks specifically about static classes, they may not understand that there was a paradigm shift from .NET to .NET Core. Because of this, a static class is not the optimal answer and therefor the options pattern should be a valid answer.
-3

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.

1 Comment

The question is about how to "access Configuration from static class" so I don't think it's very useful to tell us here how to get configurations "without having to reference these statically"
-5

The IConfiguration is Injectable anywhere within the Project. But in the case of static class, the option I am using and maybe only approach...

var Configuration = new ConfigurationBuilder()
                       .AddUserSecrets<Startup>()
                       .Build();

And, you can add required section, such in this code block above, I added 'UserSecrets'.

3 Comments

You can't DI into a static, so this is the wrong answer.
Hi billb, this is what I mentioned above. We cannot DI into static class, and this is why the code block above. Where no DI is occurring but allowing to access configuration, such as 'UserSecrets' in code block
Well, you can't DI into a static class, BUT you can DI into a class that contains static private members. Adding to the start up service is probably the best approach, but it couples your projects together and makes reuse more difficult. I tend to include statics within my service classes where they can be completely encapsulated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.