dotnet not loading appsettings.json if executing dotnet outside publish folder

I've been hovering around this issue for quite some time now and still haven't found an answer, nor another post dealing with the same problem.

I have published a .net 5.0 Website and everything works fine if I run dotnet inside the same published folder. in this folder I also have a file called appsettings.json with all the configuration needed by the application ie:

+ path
 + to
   + karinapi
     - MinosIT.Karin.API.dll
     - appsettings.json

When I run dotnet inside the folder, everything works fine and the settings are read without any problem:

cd /path/to/karinapi
dotnet MinosIT.Karin.API.dll

The result is ok ie:

user@machine$ dotnet MinosIT.Karin.API.dll
info: MinosIT.Karin.API.Program[0]
      Inicializando migración
info: MinosIT.Karin.Migrations.HDIKarinMigrations[0]
      Verificando migraci+on
info: MinosIT.Karin.Migrations.HDIKarinMigrations[0]
      Checking whether journal table exists..
info: MinosIT.Karin.Migrations.HDIKarinMigrations[0]
      Fetching list of already executed scripts.
info: MinosIT.Karin.API.Program[0]
      finalizando migración     

but when I try to follow this guide: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx?view=aspnetcore-5.0 it says that you have to create a service and run the app like this

/usr/bin/dotnet /path/to/karinapi/MinosIT.Karin.API.dll

The problem is that when I try to run my app while being outside the publish folder, dotnet doesn't seem to find appsettings.json file ie:

user@mymachine$ pwd
/path/to/
user@mymachine$ /user/bin/dotnet /path/to/karinapi/MinosIT.Karin.API.dll

Application fails and throws this error:

 user@mymachine$ dotnet karinapi/MinosIT.Karin.API.dll

Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'implementationInstance')

at Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions.AddSingleton[TService](IServiceCollection services, TService implementationInstance)
at MinosIT.Karin.API.Startup.ConfigureServices(IServiceCollection services) in D:\Minos IT\Karin\MinosIT.Karin\BackEnd\MinosIT.Karin.api\Startup.cs:line 72
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs:line 399
at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.InvokeCore(Object instance, IServiceCollection services)
at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.<>c__DisplayClass9_0.g__Startup|0(IServiceCollection serviceCollection)
at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.Invoke(Object instance, IServiceCollection services)
at Microsoft.AspNetCore.Hosting.ConfigureServicesBuilder.<>c__DisplayClass8_0.b__0(IServiceCollection services)
at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.UseStartup(Type startupType, HostBuilderContext context, IServiceCollection services, Object instance)
at Microsoft.AspNetCore.Hosting.GenericWebHostBuilder.<>c__DisplayClass13_0.b__0(HostBuilderContext context, IServiceCollection services)
at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
at Microsoft.Extensions.Hosting.HostBuilder.Build()

I'm using Microsoft.Extensions.Configuration.

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

    public IConfiguration Configuration { get; }
    ...

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

and inside StartUp.ConfigureServices I'm using:

var connectionString = Configuration.GetConnectionString("ConnectionStringName");
var section = Configuration.GetSection("CustomSection").Get<CustomConfiguration>();

When I debug, my code via logging I understand that the problem might be the ASP.NET Core doesn't know where to read appsettings.json, I have looked at dotnet cli docs, environment variables, other configuration types and I can't seem to find the problem. I really don't know what else to look for, any guidance or help will be appreciated.

Thanks in advance for your help.

Upvotes: 5

Views: 1607

Answers (2)

C Weber
C Weber

Reputation: 11

Similar to your approach, a more concise expression would be to use AppContext.BaseDirectory.

I found a good resource which describes many ways at getting the "current" directory: 6 ways to get the current directory in C#

    public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((context, config) =>
            {
                config.SetBasePath(AppContext.BaseDirectory);
                config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            }
            );

Upvotes: 0

Found a solution, I'm posting here in case someone else is struggling with the same error:

inside Program.cs I changed from:

        public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                }
                );

to

        public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((context, config) =>
                {
                    var assembly = Assembly.GetExecutingAssembly();
                    var currentPath = System.IO.Path.GetDirectoryName(assembly.Location);

                    config.SetBasePath(currentPath);
                    config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false);
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                }
                );

Upvotes: 2

Related Questions