266

In earlier versions, we had Startup.cs class and we get configuration object as follows in the Startup file.

public class Startup 
{
    private readonly IHostEnvironment environment;
    private readonly IConfiguration config;

    public Startup(IConfiguration configuration, IHostEnvironment environment) 
    {
        this.config = configuration;
        this.environment = environment;
    }

    public void ConfigureServices(IServiceCollection services) 
    {
        // Add Services
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 
    {
        // Add Middlewares
    }

}

Now in .NET 6 and above (With Visual Studio 2022), we don't see the Startup.cs class. Looks like its days are numbered. So how do we get these objects like Configuration(IConfiguration) and Hosting Environment(IHostEnvironment)

How do we get these objects, to say read the configuration from appsettings? Currently the Program.cs file looks like this.

using Festify.Database;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();

builder.Services.AddDbContext<FestifyContext>();


////////////////////////////////////////////////
// The following is Giving me error as Configuration 
// object is not avaible, I dont know how to inject this here.
////////////////////////////////////////////////


builder.Services.AddDbContext<FestifyContext>(opt =>
        opt.UseSqlServer(
            Configuration.GetConnectionString("Festify")));


var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

I want to know how to read the configuration from appsettings.json ?

2

14 Answers 14

381

WebApplicationBuilder returned by WebApplication.CreateBuilder(args) exposes Configuration and Environment properties:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
...
ConfigurationManager configuration = builder.Configuration; // allows both to access and to set up the config
IWebHostEnvironment environment = builder.Environment;

WebApplication returned by WebApplicationBuilder.Build() also exposes Configuration and Environment:

var app = builder.Build();
IConfiguration configuration = app.Configuration;
IWebHostEnvironment environment = app.Environment;

Also check the migration guide and code samples.

Applicable to , , .

3
  • 2
    In earlier versions, we could access IHttpContextAccessor via dependency injection on the Configure() method. In .NET 6, how can we access the HttpContextAccessor in Program.cs? Commented Nov 28, 2021 at 2:44
  • 3
    What if it's not a web app?
    – Fandango68
    Commented Jun 8, 2022 at 3:07
  • 1
    @Fandango68 there are a lot of answers covering that. For example
    – Guru Stron
    Commented Jun 8, 2022 at 10:02
47

In Program.cs, the WebApplicationBuilder is created shown below.

var builder = WebApplication.CreateBuilder(args);

Once we have the builder created, the configuration is available.

Let's assume you have the default appSettings.json in place. The example code below would return the configuration Default log level setting from the JSON configuration file.

builder.Configuration["Logging:LogLevel:Default"] // returns "Warning"

Once the app is running, you can access the Configuration settings via dependency injection in other classes of your application.

public MyClass(IConfiguration configuration)
{
   var logLevel = configuration["Logging:LogLevel:Default"];
}

A nice feature worth considering it to create a class that represents your settings and then bind the configuration to an instance of that class type. For example, let's assume you create a new class called MyAppSettings with the same structure as your appSettings.json, you can do the following:

var myAppSettings = builder.Configuration.Get<MyAppSettings>();
string logLevel = myAppSettings.Logging.LogLevel.Default;
5
  • Class MyAppSettings is a better approach. How can i register this data (AddSingleton?) and then where ever i need it i just inject IMyAppSettings and then start using it? Commented Jun 26, 2022 at 5:47
  • 1
    Yep. builder.services.AddSingleton<MyAppSettings>(myAppSettings) Then just inject. Commented Jun 27, 2022 at 13:05
  • 1
    How-to access to configuration in class C? Class A calls Class B, and Class B calls Class C
    – Kiquenet
    Commented Jul 1, 2022 at 9:09
  • Can you elaborate on the last part of your answer please? As this doesn't make much sense as Kiquenet has mentioned.
    – bsod_
    Commented Oct 11, 2022 at 13:29
  • If you have dependency injection set up look at MyClass(IConfiguration configuration) example in the response @Kiquenet
    – BorisD
    Commented Apr 25, 2023 at 5:19
20

I know the question originally asks for ASPNetCore but if you happen to looking to do the same for a worker service, and landed here like I did, hopefully, this answer helps you.

Worker Service uses IHostBuilder instead of IWebApplicationBuilder and that does not expose a Configuration property, but you can accept an instance of IHostBuilderContext into the ConfigureServices method, which does expose a Configuration instance.

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices((context, services) =>
    {
         var settings = context.Configuration.Get<Settings>();
    })
    .Build();
2
  • 1
    Thank you...This was a life saver. However, when I'm trying to do AddDBContext() here it is throwing error that it can't consume Scoped service since BackgroundService itself is a Singleton one. It would be really helpful if you know any workaround for that & share here. Commented Dec 14, 2023 at 8:00
  • This was just what I was looking for. It works for Azure Functions under the isolated model too, as they are effectively worker services. Commented May 9 at 15:22
15

.NET 6 already gives builder object in Program.cs

var builder = WebApplication.CreateBuilder(args);

Just use this builder to access configuration and Environment as an example to get ConnectionString from app.settings.cs as follows:

builder.Services.AddDbContext<DataContext>( options =>
{
  options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnectiion"));
});
0
15

//.NET6 Program.cs -(to get the application configuration properties)

var builder = WebApplication.CreateBuilder(args);

builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
builder.Configuration.AddJsonFile($"appsettings.Dev.json", optional: true);
builder.Configuration.AddEnvironmentVariables();

// projectwide instances
  public IConfiguration _configuration;
        public AccountsAPIController(IConfiguration configuration)
        {
            _configuration = configuration;
        }

// _configuration.GetConnectionString("DefaultConnection");
4
  • 12
    There are six existing answers to this question, including a top-voted, accepted answer with well over one hundred votes. Are you certain your solution hasn't already been given? If not, why do you believe your approach improves upon the existing proposals, which have been validated by the community? Offering an explanation is always useful on Stack Overflow, but it's especially important where the question has been resolved to the satisfaction of both the OP and the community. Help readers out by explaining what your answer does different and when it might be preferred. Commented Apr 15, 2022 at 0:11
  • Which is namespace for IConfiguration ? Now, I want use NET 6 Minimal APIs, using Services class for IConfiguration.
    – Kiquenet
    Commented Jul 1, 2022 at 7:28
  • 1
    @Kiquenet namespace for IConfiguration is Microsoft.Extensions.Configuration. Commented Sep 7, 2022 at 23:45
  • 2
    I believe this should have been the proposed answer as it clearly shows how to load extra json files (and env variables, but this is done by default). Commented Nov 20, 2022 at 7:28
7

This worked for me ---

// Read in from JSON file
builder.Services.Configure<ConnectionKeys>(builder.Configuration.GetSection("ConnectionKeys"));
1
  • This not worked for me, i am pulling my hair out, api compiles but at runtime says: 'Unable to resolve service for type 'the.type' while attempting to activate 'api.endpoints.userendpoint'.' Commented Nov 9, 2023 at 22:06
7

All you need is to add "builder." before your Configuration

Like:

builder.Services
       .AddDbContext<FestifyContext>
    (opt =>opt.UseSqlServer(builder.Configuration
                                   .GetConnectionString("Festify")));

4

This is slightly different than prior answers and I include this since I was reviewing something like this.

In your Program.cs you can also group code in a method and call that to keep it less run-on a bit or to group similar things. I will not put all the code in; I will not put a full list of using directives here but just enough to demonstrate the technique and I will leave out some method code. This is not enough or even perhaps too much for your solution and will need your custom touchup.

using AutoMapper;
using MicroKnights.Log4NetHelper;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
...
//all your using directives
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

//a variable to hold configuration
IConfiguration Configuration;

var builder = WebApplication.CreateBuilder(args);
Configuration = builder.Configuration;

// call some methods
ConfigureAuth(builder.Services);
ConfigureRedis(builder.Services);
ConfigureSession(builder.Services);
ConfigureMvc(builder.Services);
ConfigureServices(builder.Services);

var app = builder.Build();
ConfigureMiddleWare(app);
app.Run();
// we are done with the main part, now the methods

void ConfigureMvc(IServiceCollection services)
{
    builder.Services.AddMvc(config =>
    {
        var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
        config.Filters.Add(new AuthorizeFilter(policy));
    })
    .AddRazorPagesOptions(options => { options.Conventions.AddPageRoute("/Home/Login", ""); })
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
        options.JsonSerializerOptions.PropertyNamingPolicy = null;
    });
}

void ConfigureSession(IServiceCollection services)
{
    builder.Services.AddSession(options =>
    {
        options.Cookie.Name = "mygreatsite_session";
        options.IdleTimeout = TimeSpan.FromMinutes(60);
    });
}

void ConfigureRedis(IServiceCollection services)
{
    var redisConfig = new RedisOptions();
    Configuration.GetSection(RedisOptions.RedisConfig).Bind(redisConfig);
    services.AddStackExchangeRedisCache(options =>
    {
        options.Configuration = redisConfig.ConnectionString;
        options.InstanceName = "mygreatsite_";
    });
    services.AddDataProtection()
        .SetApplicationName("MyGreatSite.Website")
        .PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(redisConfig.ConnectionString), "DataProtection-Keys");
}

void ConfigureMiddleWare(WebApplication app)
{
    if (builder.Environment.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseRouting();
    app.UseCors("default");
    app.UseCookiePolicy();
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseSession();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute().RequireAuthorization();
        endpoints.MapControllerRoute(
            name: "Default",
            pattern: "{controller=Home}/{action=Login}"
        );
    });
}
2
  • Hi @Mark Schultheiss, did you miss the ConfigureAuth method def? Where is it?
    – VivekDev
    Commented May 27, 2022 at 2:26
  • 1
    @VivekDev This is more to illustrate how to use a method by constructing and calling it rather than the full set of code for any specific use case as noted in my answer I left out some method code for brevity and leave that to your specific use case. Commented May 27, 2022 at 12:59
3

The following codes worked for me:

Program.cs:

var builder = WebApplication.CreateBuilder(args);
string connString = builder.Configuration.GetConnectionString("conStr");
ConnectionString = connString;

...

partial class Program
{
    public static string? ConnectionString { get; private set; }
}

calling class:
string cnStr = Program.ConnectionString;
2
  • This worked perfectly! I didn't think to use a partial class like this. This isn't the "correct" way, but until someone posts a working solution for something as simple as a friggin' connection string (for all of us NOT using EF and it's security holes and poor performance).
    – MC9000
    Commented Jan 18, 2022 at 16:13
  • The only good solution is that as you have multiple configuration values, you use them in different classes without it being laborious.
    – bmi
    Commented Apr 20, 2022 at 9:29
2

I resolved this issue by simple way:

In Program.cs:

using SomeAppName.Startup;

    WebApplication.CreateBuilder(args)
        .RegisterServices()
        .Build()
        .SetupMiddleware()
        .Run();

Next:

public static WebApplicationBuilder RegisterServices(this WebApplicationBuilder builder)
 {
      BuildConfiguration(builder.Environment);
      //// Any code
 }

Finally:

private static IConfiguration BuildConfiguration(IHostEnvironment env)
        {
            var configurationBuilder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("./Configuration/appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile("./Configuration/appsettings.other.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"./Configuration/appsettings.{env.EnvironmentName}.json", optional: true)
                .AddJsonFile($"./Configuration/appsettings.other.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();

            Configuration = configurationBuilder.Build();
            return Configuration;
        }
2

An alternative : do I really need DI when it comes to settings ?

Especially when I want those settings from environment variables, which is often the case with containerized environments, and maybe avoid leaking secrets in json files.

Then just have a static class like for example :

public static class SettingsService
{

    private static Settings _settings = null;

    public static Settings Settings
    {
        get
        {
            if (_settings == null)
            {
                _settings = new Settings()
                {
                    hostmail = Environment.GetEnvironmentVariable("hostmail") ?? "",
                    hostmailuser = Environment.GetEnvironmentVariable("hostmailuser") ?? "",
                    hostmailpass = Environment.GetEnvironmentVariable("hostmailpass") ?? "",
                    hostmailport = int.Parse(Environment.GetEnvironmentVariable("hostmailport") ?? "993"),
                    LogLevel = Enum.Parse<LogLevel>(Environment.GetEnvironmentVariable("LogLevel") ?? "Information"),
                    natsurl = Environment.GetEnvironmentVariable("natsurl") ?? "nats://localhost:4200",
                    natsnkeypubkey = Environment.GetEnvironmentVariable("natsnkeypubkey") ?? "",
                    natsnkeypath = Environment.GetEnvironmentVariable("natsnkeypath") ?? "",
                    roles = (Environment.GetEnvironmentVariable("roles") ?? "").Split(';'),
                    poolsize = int.Parse(Environment.GetEnvironmentVariable("poolsize") ?? "10"),
                    tmpfolder = Environment.GetEnvironmentVariable("tmpfolder") ?? "temp",
                    fontsfolder = Environment.GetEnvironmentVariable("fontsfolder") ?? "fonts"
                };

            }
            return _settings;
        }
    }
}

and a program.cs like :


var sets = SettingsService.Settings;

IHost host = Host.CreateDefaultBuilder(args).ConfigureAppSettings()
    .ConfigureServices(services =>
    {
        if (sets.serverrole == "inboxsignaler")
        {
            services.AddHostedService<InboxSignaler>();
        }
        services.AddNats(options =>
          {
              options.Url = sets.natsurl;
              options.SetNkey(sets.natsnkeypubkey, sets.natsnkeypath);
          });
    })
    .Build();

await host.RunAsync();

my 2 cents...

1

If you have defined a token in your appsetting.json file, you can define this json token in program cs as follows:

appsettting.json:

  "AppSettings": {
    "Token": "token"
  },

program cs:

var key = Encoding.ASCII.GetBytes(builder.Configuration.GetSection("Appsettings:Token").Value);
1
  • Has nothing to do with the question Commented Apr 15 at 17:46
0

Fully qualify it like this:

var builder = Microsoft.AspNetCore.Builder.WebApplication.CreateBuilder(args);
0

For me adding below piece of code for the Worker Service Template

 In appsettings.json
    ....
    "Worker": {
              "TillTimeInMinutes": 1,
              "Crop": "Grain"
              }

In WorkerConfig File

     WorkerConfig.cs
     {
          public int TillTimeInMinutes { get; set; }
          public string Crop { get; set; }
     }

And in Program.cs file

     builder.Services.Configure<WorkerConfig>(builder.Configuration.GetSection("Worker"));
1
  • 1
    Following this implementation, how do I then access the settings in a view?
    – Goober
    Commented Feb 2 at 2:01

Not the answer you're looking for? Browse other questions tagged or ask your own question.