1

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.

3
  • Why do you use slash "Urls/SampleUrl"? Docs says it should be "Urls:SampleUrl" Commented Apr 25, 2020 at 15:12
  • I'm getting null calling using ':' too. I'm even getting error when i try to call something like "ConnectionStrings" Commented Apr 25, 2020 at 15:17
  • Quick answer: the Section seems to be "Url" Commented Apr 25, 2020 at 15:25

3 Answers 3

5

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");

Sign up to request clarification or add additional context in comments.

4 Comments

The problem is that i use static class, so i can't simply inject ``` IConfiguration ``` to call ``` GetValue() ``` method. I also can't use [] on ``` Configuration ``` because it doesn't provide ways to do that. Calling ConfigurationManager.AppSettings also doesn't help
@Nicefsf, my bad. Edited my answer for your case
This solution works well for me. I found it before i started this thread. The problem is that i don't think this solution is good in terms of good code style, so i'm event thinking about redesigning my class. Thanks for the solution
Ohh static - this is not the right way too do. Use IConfiguration, and don’t use static props for config in this way. It’s not the DI way
2

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

4 Comments

Well, first of all ConfigurationManager actually works not the way i expected. As i mentioned above, i understood that my desing is wrong at some point. The thing is that this class hides all logic for calling my api's, and i decided to store api's url instead of hardcoding it in my class. Thanks for your detailed response
@Nicefsf apologize for using the expression "does not make sense". My intention was only to emphasize the concept. Sorry if I used a term that you have interpreted as rude or inappropriate. Don't worry about design errors, we are all here to share ideas and to learn new things day by day. Happy coding man.
@Nicefsf as a sidenote, if you are trying to encapsulate the logic to access a third party API opt for a so called typed HTTP client. You can find full documentation and examples here.
@Enrice Massone, i wrote some classes to incapsulate logic of calling all my api's method, sending data to them. I think i should at least update it to use factory. Thanks for help
-2

Use...

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

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

2 Comments

I'm still getting null when trying to obtain any section of my json file
injected ? how?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.