ASP.NET Core—access Configuration from static class

后端 未结 13 1982
我在风中等你
我在风中等你 2021-02-01 00:27

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

相关标签:
13条回答
  • 2021-02-01 00:44

    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.

    0 讨论(0)
  • 2021-02-01 00:45

    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");
    
    0 讨论(0)
  • 2021-02-01 00:46

    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;
    
    
    0 讨论(0)
  • 2021-02-01 00:48

    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"
       }
     }
    
    0 讨论(0)
  • 2021-02-01 00:52

    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;
      }
    
    0 讨论(0)
  • 2021-02-01 00:56

    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.

    0 讨论(0)
提交回复
热议问题