Skip to main content

Fixed: appsettings.json Is Ignored When an ASP.NET Core DLL Runs from Another Folder

· 6 min read
Jagdish Kumawat
Founder @ Dewiride

I published my API and started it with dotnet publish/Dewiride.Inventory.Api.dll. It ran and it answered, and it logged SQL statements that its appsettings.json turns off. The file was right there, and nothing said it wasn't being read.

What I Was Doing​

I was running a published .NET 10 API on my own machine, to check it the way production would run it. From the solution folder:

Terminal
dotnet publish src/Dewiride.Inventory.Api -c Release -o publish
ASPNETCORE_URLS=http://localhost:5191 ConnectionStrings__Inventory="Server=127.0.0.1;Port=3306;Database=inventory;User ID=inventory_app;Password=$(grep '^MYSQL_PASSWORD=' .env | cut -d= -f2-);SslMode=Required" dotnet publish/Dewiride.Inventory.Api.dll

Then I sent one request to http://localhost:5191/api/v1/categories.

What I Expected​

The API's appsettings.json has "Microsoft.EntityFrameworkCore.Database.Command": "Warning", so no SQL statements in the log.

What I Got​

A SQL statement, for that one request. These are the messages from its JSON log:

API log (the messages)
info: Now listening on: http://localhost:5191
info: Application started. Press Ctrl+C to shut down.
info: Hosting environment: Production
info: Content root path: /Users/you/projects/dewiride-inventory-api
info: Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='0']

The API log from the published app, with Content root path showing the solution folder, and an Executed DbCommand line that appsettings.json should have hidden.

There's no error, and no warning about a missing file.

What I Checked​

Whether the file was published. It was. ls publish included:

Output (the settings files)
appsettings.Development.json
appsettings.json

The log's Content root path. It says the solution folder, and not publish. That's the clue.

What the content root does. Microsoft's fundamentals page lists it as the base path for "configuration files", and its generic host page says the default builder "Sets the content root to the path returned by GetCurrentDirectory". So it's the folder I started in, wherever the DLL is.

Why there's no error. Its configuration page lists the source as JsonConfigurationProvider for 'appsettings.json' (Optional). A missing file is fine, as far as the host is concerned.

Why It Happens​

ASP.NET Core looks for appsettings.json in the content root, and the content root is the current folder when the app starts. I started it in the solution folder, which has no appsettings.json. That's allowed, so the app carried on with its built-in defaults. An app with sensible defaults runs fine like this, so it's easy to miss. The same happens with the executable, publish/Dewiride.Inventory.Api.

The Fix​

Any of these works, with the same two variables set as before.

1. Start it from inside the folder:

Terminal
cd publish
dotnet Dewiride.Inventory.Api.dll

2. Pass --contentRoot, with a full path. $PWD is the folder you're in, in both bash and PowerShell:

Terminal
dotnet publish/Dewiride.Inventory.Api.dll --contentRoot "$PWD/publish"

Watch out for a relative path here. It's relative to the DLL's folder, and not yours, so --contentRoot publish looks in publish/publish:

Output
Unhandled exception. System.IO.DirectoryNotFoundException: /Users/you/projects/dewiride-inventory-api/publish/publish/

3. Set ASPNETCORE_CONTENTROOT, which suits a service, whose start folder you may not control:

Terminal
ASPNETCORE_CONTENTROOT="$PWD/publish" dotnet publish/Dewiride.Inventory.Api.dll

After the Fix​

The same request, from inside the folder:

API log (the messages)
info: Now listening on: http://localhost:5191
info: Application started. Press Ctrl+C to shut down.
info: Hosting environment: Production
info: Content root path: /Users/you/projects/dewiride-inventory-api/publish

The API log from the published app, with Content root path showing the publish folder, and no Executed DbCommand line.

The content root is publish, and the SQL statement has gone. --contentRoot and ASPNETCORE_CONTENTROOT gave the same log.

Common Mistakes​

MistakeWhat happensDo this instead
Assuming the DLL's folder is the content rootSettings are skipped, with no errorRead Content root path in the log
Passing a relative --contentRootDirectoryNotFoundExceptionUse a full path
Testing only with dotnet runIt sets the folder for youRun the published output too

Troubleshooting​

SymptomLikely causeFix
Settings differ between a terminal and a serviceThe service starts in another folderSet its working folder, or ASPNETCORE_CONTENTROOT
wwwroot files return 404The same cause: it's under the content rootThe same fixes
It still ignores a settingAn environment variable overrides itSee the order

Conclusion​

The content root is the folder you start in, and appsettings.json is optional. So start a published app from its own folder, or tell it where that is, and check Content root path in the log.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.