Xucong
Xucong

Reputation: 338

ASP.NET Core 2.1 app not picking up appsettings.Development.json even though I specify ASPNETCORE_ENVIRONENT=Development explicitly. Why?

So I am working on an ASP.NET Core 2.1 Web API. I specified two sets of configurations for "Development" and "Production" explicitly by the following two functions:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<DataContext>(option => option
        .UseMySql(Configuration.GetConnectionString("DefaultConnection"))                                              
}

public void ConfigureDevelopmentServices(IServiceCollection services)
{
    services.AddDbContext<DataContext>(option => option
        .UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
}

In the appsettings.json, I have:

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost; Database=datingApp; Uid=appuser; Pwd=zhanxucong"
    }
}

In the appsettings.Development.json, I have:

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    },
    "ConnectionStrings": {
      "DefaultConnection": "Data Source=DatingApp.db"
    }
  }
}

When I learned through the tutorial, the instructor said that by convention, when ASPNETCORE_ENVIRONMENT=Development is set, ASP.NET Core will call the more specific configure function (i.e. ConfigureDevelopmentServices) and use the more specific appsettings config file (i.e. appsettings.Development.json). And I can confirm that it had worked fine on my Windows and Mac. However, when I run this app on Linux, after running ef migration with the above settings, I get the following errors:

info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core 2.1.4-rtm-31024 initialized 'DataContext' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: None
System.ArgumentException: Keyword not supported: 'server'.
   at Microsoft.Data.Sqlite.SqliteConnectionStringBuilder.GetIndex(String keyword)
   at Microsoft.Data.Sqlite.SqliteConnectionStringBuilder.set_Item(String keyword, Object value)
   at System.Data.Common.DbConnectionStringBuilder.set_ConnectionString(String value)
   at Microsoft.EntityFrameworkCore.Sqlite.Storage.Internal.SqliteRelationalConnection.CreateReadOnlyConnection()
   at Microsoft.EntityFrameworkCore.Sqlite.Storage.Internal.SqliteDatabaseCreator.Exists()
   at Microsoft.EntityFrameworkCore.Migrations.HistoryRepository.Exists()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_1.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Keyword not supported: 'server'.

Any idea why this error will happen? Is it related to Linux being case-sensitive? Thanks!

Update: My Program class and my StartUp class (default ctor provided by dotnet-cli tool by running "dotnet new webapi":

Program class:

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

StartUp class:

public class Startup
{
    public IConfiguration Configuration { get; }

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

    // ConfigureServices, ConfigureDevelopmentServices, Configure methods.
}

Upvotes: 5

Views: 6362

Answers (2)

Xucong
Xucong

Reputation: 338

Thanks for all the answers provided. I really appreciate it and I learned a lot.

As for my bug, it is actually due to a very stupid mistake:

In my appsettings.Development.json file, the "ConnectionStrings" is nested within "Logging". Therefore, when the ConfigureDevelopmentServices method is invoked, it will not be able to find ConnectionStrings in the appsettings.Development.json file and will fall back to configurations specified in appsettings.json, which is configured for connecting to a MySQL database. Hence the errors shown in my problem statement.

This observation is inspired by this GitHub issue.

Upvotes: 11

prisar
prisar

Reputation: 3195

Keep three nested files like appsettings.json, appsettings.Development.json and appsettings.Production.json. Then environment name from env. Mention which file to use at Startup.cs and in bash set environment using,

$ export ASPNETCORE_ENVIRONMENT=Development

Take the appropriate file depending on the environment. Replace the startup constructor with this.

public class Startup
{
    public Startup(IConfiguration configuration, IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();

        Configuration = builder.Build();
    }

    public IConfiguration Configuration { get; }

    // code removed...
}

Please be consistent while writing environment variable names. Linux environment variable names are case-sensitive.

Upvotes: 1

Related Questions