The blog of Phil Stewart, a UK web developer and tech geek.

Turbinado Logo

Why won't my ASP.NET Core app recognise my user secrets?

25 January 2024

I've been working on updating a .NET Framework WCF service to ASP.Net Core using CoreWCF, and everything was going nicely until I decided to swap out my database connection string from appsettings.json to dotnet user secrets. I've used user secrets on a couple of other projects, so was already familiar with doing the setup, which all worked as expected: the UserSecretsId attribute was added to the csproj project file, and I set my connection string secret on the commandline exactly as I'd done in previous projects. According to the app secrets documentation, user secrets would be enabled automatically for the Development environment without me having to do anything extra, so it should all Just Work. So I launch the debug build in Visual Studio, but instead of everything Just Working I get a nasty exception as soon as something tries to touch the database, and it's quite clear from the logs that the connection string has not been picked up from user secrets. The entire rest of my afternoon was then consumed trying to debug why.

The docs say user secrets are only enabled in the Development environment, so I double check this and confirm that after creating my builder with var builder = WebApplication.CreateBuilder(args); the builder's environment is indeed Development, having set a breakpoint so I can inspect it in the Visual Studio Locals window. I also observed that the expected configuration values were missing in builder.Configuration, so it seemed that either AddUserSecrets was not being called, or it was being called but wasn't working. The internet was not forthcoming with clues, so the next step was to try calling AddUserSecrets directly after creating the builder, and after a bit more interneting I figured out how to do that:

Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddUserSecrets("uuid string");

Launch the app, and hey presto: secrets have been found, the builder configuration knows the connection string, and the app behaves as expected. So why wasn't it working via CreateBuilder, or CreateSlimBuilder? After more deep diving poking into the ASP.NET Core source, I eventually figured out that the builders called AddUserSecrets using a different method signature, passing in the Assembly from which to extract the UUID. So I tried doing that directly:

Program.cs
var builder = WebApplication.CreateBuilder(args);
var appAssembly = Assembly.Load(new AssemblyName(builder.Environment.ApplicationName));
builder.Configuration.AddUserSecrets(appAssembly);

Launch the app, secrets not found. Poking around at appAssembly in the Locals there clearly wasn't anything there for the UserSecretsIdAttribute. Why? It was then that I discovered this stackoverflow with the top answer being to check for <GenerateAssemblyInfo>true</GenerateAssemblyInfo> in the project file, so I take a look and aha! GenerateAssemblyInfo was false, so the UserSecretsId attribute was not being included in the assembly, causing AddUserSecrets to fail. Flip GenerateAssemblyInfo to true, relaunch, and hey presto, fixed forever. I don't know why GenerateAssemblyInfo was false before, maybe it made sense to the way the original .NET Framework WCF implementation was being deployed, but whatever the reason it led to a classic case of an afternoon of debugging for a simple one-line fix.