Nicefsf
Nicefsf

Reputation: 140

Asp.Net Core configuration in static class

I want to read url from my appsettings.json file within static class. I tried something like

private static string Url => ConfigurationManager.GetSection("Urls/SampleUrl").ToString();

But whenever i try to call GetSection() method i get null value.

  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "ConnectionStrings": {
    "cs1": "some string",
    "cs2": "other string"
  },
  "Urls": {
    "SampleUrl": "google.com"
  },
  "AllowedHosts": "*"

I simply want to read some data from appsettings. According to docs i should not somehow register my standart appsettings.json file because Host.CreateDefaultBuilder(args) in Program class does it for me by default.

Upvotes: 1

Views: 13579

Answers (3)

mrdnk
mrdnk

Reputation: 685

Use...

Configuration.GetSection("Urls").GetValue<string>("SampleUrl");

Update: Sorry, this was based on the assumption, that Configuration had been already injected in

Upvotes: -2

Enrico Massone
Enrico Massone

Reputation: 7338

The ConfigurationManager api does not work the way you expect it to in ASP.NET core. It won't throw any exception, but simply returns null whenever you call its methods, as you are experiencing.

In ASP.NET core you have new objects and APIs to pass configuration to your application. They are based around the idea of configuration sources which can be registered with a configuration builder which, once builded, gives you the configuration object. The configuration source for the appsettings.json file is automatically taken into account if you use the default host builder, so you have it out of the box. Full documentation is available here.

The other piece you are missing is the DI container that you have in ASP.NET core. The framework is strongly opinionated and guides you to a design based on the dependency injection pattern. Each time your services need something they simply ask for it via a constructor parameter and some other actor (the DI container) will take care of resolving the dependency and to inject the requested object. One of the interfaces that are automatically registered in the DI container is the IConfiguration interface, which is basically the configuration that you have passed to your application.

That said in my opinion your design is not correct. Accessing the application configuration from a static class does not make sense. Static classes are usually meant to be the container of static methods, which are basically functions receiveing an input and producing an output. Think of them as pure functions which implements calculations for you and can be used as helpers to solve a particular problem. Just to give you an example, consider the following static class:

public static class StringHelpers 
{
  // notice that this is a pure function. This code does not know it is running inside an application having some sort of injected configuration. This is only an helper function
  public static string Normalize(string str)
  {
    if (str is null)
    {
      throw new ArgumentNullException(nameof(str));
    }

    return str.Trim().ToUpperInvariant();
  }
}

It is entirely possible that your static methods needs some of your configuration as an input in order to work. In this case you should opt for the following design:

public interface IUrlProvider 
{
  string GetUrl();
}

public class ConfigurationBasedUrlProvider: IUrlProvider
{
  private const string DefaultUrl = "https://foo.example.com/foo/bar";
  private readonly IConfiguration _appConfiguration;

  // ask the DI container to inject the configuration. Here you have the content of appsettings.json for free. Interface IConfiguration is automatically registered with the DI container
  public ConfigurationBasedUrlProvider(IConfiguration configuration)
  {
    _appConfiguration = configuration ?? throw new ArgumentNullException(nameof(configuration));
  }

  public string GetUrl()
  {
    var configuredUrl = _appConfiguration.GetSection("Urls")["SampleUrl"];
    var safeUrl = string.IsNullOrWhiteSpace(configuredUrl) ? DefaultUrl : configuredUrl;
    return StringHelpers.Normalize(safeUrl);
  }
}

Upvotes: 2

Mateech
Mateech

Reputation: 1074

As it mentioned here, you can add static property to your Startup.cs

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
    StaticConfig = configuration;
}

public static IConfiguration StaticConfig { get; private set; }

And use in static class:

var x = Startup.StaticConfig.GetSection("whatever");

Upvotes: 5

Related Questions