With aspnet core 3.x, the default Text JSON serializer as well as the Newtonsoft extension (if you're still holding on to Newtonsoft like I am) apply a camel casing naming strategy.
This means that for your upper case properties in C# land, they get translated to lower case starting letters in javascript. This is great. Unless you're dealing with a legacy codebase where the javascript is expecting the starting upper cases.
The fix is easy. Just set contract resolver in your Startup to an instance of DefaultContractResolver.
Can you just do:
opts.SerializerSettings.ContractResolver = new DefaultContractResolver()
Looks like their DefaultNamingStrategy still behaves like your PreserveCaseNamingStrategy, where it just returns the name of the property.