7 Reeds
7 Reeds

Reputation: 2539

ASP.NetCore 2.2 reading in appsettings.json

ASP.NetCore 2.2, VisualStudio 2019

I am trying to figure out how to convert a web.configfile to appsettings.json and I am missing someting.

I have a startup.cs file that looks like (edited for brevity):

using System;
using MyCoolApp.Models.Commodities;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace MyCoolApp {
    public class Startup {
        public Startup(IHostingEnvironment env) {
            var builder = new ConfigurationBuilder()
                .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
                .AddJsonFile("appsettings.json", true, true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true)
                .AddEnvironmentVariables();

            Configuration = builder.Build();
        }

        private IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services) {
            services.AddDistributedMemoryCache();

            services.Configure<IISServerOptions>(
                options => { 
                    options.AutomaticAuthentication = false; 
                }
            );

            services.AddMvc().SetCompatibilityVersion(
                CompatibilityVersion.Version_2_2
            );

            var foo = Configuration.GetConnectionString("CommoditiesContext");
            services.AddDbContext<CommoditiesContext>(
                options => options.UseSqlServer(
                    Configuration.GetConnectionString("CommoditiesContext")
                )
            );

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
            ...
        }
    }
}

Note the var foo = Configuration.GetConnectionString(...) line.

I have a web.config file that looked like (heavily edited):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="CommoditiesContext" connectionString="Server=mydb.company.com;Initial Catalog=Things;Integrated Security=True;providerName=System.Data.SqlClient;" />
  </connectionStrings>
</configuration>

I have turned this into the "top level" appsettings.json file:

{
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },
    "AllowedHosts": "*",
    "connectionStrings": {
        "CommoditiesContext": "Server=mydb.company.com;Initial Catalog=Things;Integrated Security=True;providerName=System.Data.SqlClient;"
    }
}

I have an appsettings.Development.json file that looks like:

{
    "Logging": {
        "LogLevel": {
            "Default": "Debug",
            "System": "Information",
            "Microsoft": "Information"
        }
    },
    "location": {
        "path": ".",
        "inheritInChildApplications": "false",
        "system.webServer": {
            "handlers": [],
            "aspNetCore": {
                "processPath": "%LAUNCHER_PATH%",
                "arguments": "%LAUNCHER_ARGS%",
                "stdoutLogEnabled": "true",
                "stdoutLogFile": ".\\logs\\stdout",
                "hostingModel": "InProcess",
                "environmentVariables": [
                    {
                        "name": "ASPNETCORE_HTTPS_PORT",
                        "value": "44375"
                    },
                    {
                        "name": "ASPNETCORE_ENVIRONMENT",
                        "value": "Development"
                    },
                    {
                        "name": "COMPLUS_ForceENC",
                        "value": "1"
                    }
                ],
                "handlerSettings": [
                    {
                        "name": "debugFile",
                        "value": "aspnetcore-debug.log"
                    },
                    {
                        "name": "debugLevel",
                        "value": "FILE,TRACE"
                    }
                ]
            },
            "modules": [],
            "isapiFilters": []
        }
    }
}

I have a `Production one as well but let's limit the noise for the moment.

My question, for now, is when I debug this locally I can set a bp on the services.AddDbContext line in startup.cs and then look at the value of foo. It is null. I have either structured the appsettings.json file incorrectly or am reading the config info incorrectly but I don't know which.

What am I missing?

Edit

program.cs

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace CalendarReservations {
    public class Program {
        public static void Main(string[] args) {
            CreateWebHostBuilder(args).Build().Run();
        }

        private static IWebHostBuilder CreateWebHostBuilder(string[] args) {
            return WebHost.CreateDefaultBuilder(args)
                .UseIIS()
                .UseStartup<Startup>();
        }
    }
}

Upvotes: 1

Views: 1694

Answers (2)

Paul Lorica
Paul Lorica

Reputation: 763

Take this out from your code (startup.cs)

var builder = new ConfigurationBuilder()
                .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
                .AddJsonFile("appsettings.json", true, true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true)
                .AddEnvironmentVariables();

            Configuration = builder.Build();

EDIT: As Kirk Pointed in the comments

You need to replace it as such

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

why? Because if you have in your Program.cs class this

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)

Then you dont need to set yourself

Default configuration Web apps based on the ASP.NET Core dotnet new templates call CreateDefaultBuilder when building a host. CreateDefaultBuilder provides default configuration for the app in the following order:

The following applies to apps using the Web Host. For details on the default configuration when using the Generic Host, see the latest version of this topic.

Host configuration is provided from: Environment variables prefixed with ASPNETCORE_ (for example, ASPNETCORE_ENVIRONMENT) using the Environment Variables Configuration Provider. The prefix (ASPNETCORE_) is stripped when the configuration key-value pairs are loaded. Command-line arguments using the Command-line Configuration Provider. App configuration is provided from: appsettings.json using the File Configuration Provider. appsettings.{Environment}.json using the File Configuration Provider. Secret Manager when the app runs in the Development environment using the entry assembly. Environment variables using the Environment Variables Configuration Provider. Command-line arguments using the Command-line Configuration Provider.

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.2

Upvotes: 1

DavidG
DavidG

Reputation: 118947

The problem is that you are setting the wrong base path for the configuration in the startup constructor. AppDomain.CurrentDomain.BaseDirectory will give you the wrong location and hence no config file will be loaded. Instead, consider using System.IO.Directory.GetCurrentDirectory() instead.

Upvotes: 3

Related Questions