0

I have console app, where I have console app project and class library

I create appSettings.json file, where I store all data.

In console app I create this code in Program.cs to work with envVariables

class Program
{
    public static IConfigurationRoot Configuration;
    private static ServiceThread _serviceThread;

    static async Task Main(string[] args)
    {
        MainAsync(args).Wait();
        // Run with console or service
        var asService = !(Debugger.IsAttached || args.Contains("--console"));

        var builder = new HostBuilder()
            .ConfigureServices((hostContext, services) => { services.AddHostedService<MonitoringService>(); });
        builder.UseEnvironment(asService ? EnvironmentName.Production : EnvironmentName.Development);

        if (asService)
        {
            await builder.RunAsServiceAsync();
        }
        else
        {
            _serviceThread = new ServiceThread();
            _serviceThread.Start("Started");
            await builder.RunConsoleAsync();
        }
    }

    static async Task MainAsync(string[] args)
    {
        // Create service collection

        var serviceCollection = new ServiceCollection();
        ConfigureServices(serviceCollection);

        // Create service provider

        IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();

        // Print connection string to demonstrate configuration object is populated
        Console.WriteLine(Configuration.GetConnectionString("DataConnection"));
    }

    private static void ConfigureServices(IServiceCollection serviceCollection)
    {
        // Build configuration
        Configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
            .AddJsonFile("appSettings.json", false)
            .Build();

        // Add access to generic IConfigurationRoot
        serviceCollection.AddSingleton<IConfigurationRoot>(Configuration);
    }
}

Now in class library I want to work with those variables.

I tried like this

public class HelpersAppService
{
    private readonly IConfigurationRoot _configuration;

        public HelpersAppService(IConfigurationRoot configuration)
        {
            _configuration = configuration;
        }

        public ServerUrlsDto GetServerUrls()
        {
            var serverUrls = _configuration.GetSection("ServerUrls").Get<ServerUrlsDto>();
            return serverUrls;
        }

        public AuthDto GetAuth()
        {
            var authData = _configuration.GetSection("Auth").Get<AuthDto>();
            return authData;
        }
    }

But problem, that I have null configuration in this method. What I'm doing wrong?

Eugene Sukh
  • 2,357
  • 4
  • 42
  • 86
  • Does this answer your question? [Reading appsettings.json from .net standard library](https://stackoverflow.com/questions/50562798/reading-appsettings-json-from-net-standard-library) – Peter B May 18 '20 at 09:34
  • You're creating an entirely new service collection / provider *outside* of the host and adding IConfigurationRoot to that. Your host is then creating a new one (internally). You haven't shown how your class is being used/injected but trying accepting `IConfiguration` instead since Host Builder does add that to *its* collection – pinkfloydx33 May 18 '20 at 09:36
  • How I can use the already created collection in-class library, or read the file? @pinkfloydx33 – Eugene Sukh May 18 '20 at 09:38
  • How are you instantiating your class library object? If it's through the DI then change the parameter type – pinkfloydx33 May 18 '20 at 09:39
  • What do you mean, I have a class library method, where I need to get value from the appSettings.json file. Service collection is instantiated in the console app. My question is how to get them in class library method? @pinkfloydx33 – Eugene Sukh May 18 '20 at 10:04

1 Answers1

0

The .NET Core framework provides many helpful extensions for you. I would suggest using them like this:

static async Task Main(string[] args)
{
    // Run with console or service
    var asService = !(Debugger.IsAttached || args.Contains("--console"));

    var builder = Host
        .CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((context, config) => config
            .SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
            .AddJsonFile("appSettings.json", false))
        .ConfigureServices((context, services) => services
            .AddSingleton<HelpersAppService>()
            .AddHostedService<MonitoringService>())
        .UseEnvironment(asService ? EnvironmentName.Production : EnvironmentName.Development);

    if (asService)
    {
        await builder.RunAsServiceAsync();
    }
    else
    {
        _serviceThread = new ServiceThread();
        _serviceThread.Start("Started");
        await builder.RunConsoleAsync();
    }
}

Update:

You will also need to inject an IConfiguration instead of an IConfigurationRoot like this:

private readonly IConfiguration _configuration;

public HelpersAppService(IConfiguration configuration)
{
    _configuration = configuration;
}

Note:

You need to also add the HelpersAppService in the ConfigureServices method for it to be part of DI and have the IConfiguration available.

crgolden
  • 4,332
  • 1
  • 22
  • 40
  • Okay, so how I can get values from appsetings file in class library method? – Eugene Sukh May 18 '20 at 10:19
  • And now I cannot use `RunAsServiceAsync()` and `RunConsoleAsync()`, because host don't have these methods – Eugene Sukh May 18 '20 at 10:22
  • @Eugene Sukh Ok I made an update. You need to add `HelpersAppService` to the `IServiceCollection` as well if you want to inject dependencies into it. – crgolden May 18 '20 at 10:24
  • Got this error now `'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: ` – Eugene Sukh May 18 '20 at 10:29
  • @Eugene Sukh For that error, whatever the `ServiceType` is that's missing, you need to also add that to the `ConfigureServices` method. I can't see what's missing you don't include that part. – crgolden May 18 '20 at 10:32
  • Sorry. Here is full message `System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: symphony_adapter_logic.AppServices.Helpers.HelpersAppService Lifetime: Singleton ImplementationType: symphony_adapter_logic.AppServices.Helpers.HelpersAppService': Unable to resolve service for type 'Microsoft.Extensions.Configuration.IConfigurationRoot' while attempting to activate 'symphony_adapter_logic.AppServices.Helpers.HelpersAppService'.)'` – Eugene Sukh May 18 '20 at 10:38
  • @Eugene Sukh Change to inject `IConfiguration` instead. Like: `public HelpersAppService(IConfiguration configuration)`. – crgolden May 18 '20 at 10:42
  • Okay, but how I need to resolve it in the constructor? Like before, just change type `IConfigurationRoot` to `IConfiguration`? – Eugene Sukh May 18 '20 at 10:43
  • @Eugene Sukh Yes exactly - try that. I will update the answer. – crgolden May 18 '20 at 10:48
  • Tried like this, I get null in _configuration in class library method – Eugene Sukh May 19 '20 at 07:25
  • @Eugene Sukh Try removing the entire call to `ConfigureAppConfiguration`. All you're doing is setting the base directory and the default `appsettings.json` file. But `CreateDefaultBuilder` sets those things automatically for you – crgolden May 19 '20 at 10:22