-2

I need access to the appsettings.json configuration in other non-controller classes in my project. Is there a good way for IConfiguration to be available globally throughout my application w/o using DI? If the IConfiguration DI could be used on non-controller classes, I'd like to know how to do that.

This is my controller where HostService has access to the IConfiguration injection.

public static IHostBuilder CreateHostBuilder(string[] args)
{
    return Host.CreateDefaultBuilder(args)
        .UseWindowsService()
        .ConfigureServices((hostContext, services) =>
        {
            services.AddHostedService<HostService>();
        }).UseSerilog();
}

I need access to IConfiguration in this non-controller class. I'm not sure how to use the DI w/ non-controller type classes, so maybe using a static type configuration variable would be a better solution to make IConfiguration available globally.

public class myTestClass 
{
    private readonly IConfiguration _config

    public myTestClass(IConfiguration config){ _config = config}
}
atiyar
  • 7,762
  • 6
  • 34
  • 75
  • Using Dependency Injection is one of the best approaches https://stackoverflow.com/questions/46940710/getting-value-from-appsettings-json-in-net-core – Svyatoslav Ryumkin Mar 09 '21 at 19:50
  • Thanks, but as mentioned, it's using the Startup class which I'm not using in my current build, so I need to figure out a way to do it w/o using that class. Is there a way to do the Dependency Injection using the current controller I'm using above w/o the Startup class? –  Mar 09 '21 at 20:11
  • 1
    It doesn't matter if you use Startup or not. You can simply `services.AddScoped(()=>{buil your configuration});` and then Inject where you want. also take a look at ConfigurationBuilder – Svyatoslav Ryumkin Mar 09 '21 at 20:33
  • here is an example of ConfigurationBuilder, if you don't want inject. https://stackoverflow.com/questions/46843367/how-to-setbasepath-in-configurationbuilder-in-core-2-0 – Svyatoslav Ryumkin Mar 09 '21 at 20:42
  • The whole point of DI is to inject your dependencies... I think you need to do more learning on what and why to use it. – Ian Kemp Mar 09 '21 at 21:04

2 Answers2

2

You can add a configuration to you DI container by adding a handling of config to you host:

public static IHostBuilder CreateHostBuilder(string[] args)
{
    return Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostContext, config) =>
        {
            config.AddJsonFile("appsettings.json", false, false);
        })
        .ConfigureServices((hostContext, services) =>
        {
            services.AddHostedService<HostService>();
        })
        .UseSerilog();
}

It makes the whole IConfiguration object available for your application:

public class TestOptions
{
    public string Data { get; set; }
}

public class HostService : BackgroundService
{
    private readonly IConfiguration _configuration;

    public HostService(IConfiguration config)
    {
        _configuration = config;
    }

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // TODO: write your code here
    }
}

I need access to IConfiguration in this custom class. I can pass an IConfiguration instance in from the HostService class, but was looking for global solution to avoid passing instances to other classes.

Dependency Injection solves a lot of different issues, and today it is a common way to develop software. It is much easier to use DI instead of avoid using it.

Igor Goyda
  • 1,949
  • 5
  • 10
  • I agree w/ the DI container idea totally which already worked fine on my current build w/ HostService. The question I have is, how can other classes in other files use the DI container feature the same way. Currently, with a class in another file, I have to pass the _config from the HostService into the constructor since it doesn’t use the injection like HostService does. For example, I have to do this, myTestClass test = new myTestClass(_config) for constructor myTestClass(IConfiguration config){} which works ok, but would like it to work the same as the HostService class if possible. Tnx. –  Mar 09 '21 at 22:54
  • Why not define that class as a service too? You could define it as scoped & create a new scope around where you are using it. You haven't given sufficient context and reasoning to describe why you aren't using DI. Step back and explain the actual problem. – Jeremy Lakeman Mar 09 '21 at 23:49
0

I actually figured out a way to make IConfiguration available throughout the application without using Injections. It's quite pointless to use IConfiguration DI for non-controller classes since it requires too many steps. Just create a static class w/ a static IConfiguration variable and assign the Iconfiguration injection parameter to it from the main controller class and it'll be available throughout the app. It's simple and easy.

Programs.cs

        public static IHostBuilder CreateHostBuilder(string[] args)
            {
                return Host.CreateDefaultBuilder(args)
                    .UseWindowsService()
                    .ConfigureServices((hostContext, services) =>
                    {
                        services.AddHostedService<HostService>();
                    }).UseSerilog();
            }   
        

HostService.cs

        public static class AppData
        {
            public static IConfiguration Config;
        }
        public class HostService : IHostedService, IDisposable
        {
            public HostSyncService(IConfiguration config)
            {
                AppData.Config = config;

                var key= new myTestClass().getKey();
            }
        }
        

myTestClass.cs

        public class myTestClass {
            public myTestClass(){}
            
            public void getKey(){
                // Non-Controller class has access to AppData.Config w/o injection
                var key= AppData.Config.GetValue<string>("appSettings:key");
            }
        }