uno.extensions
uno.extensions copied to clipboard
appsettings.json in Shared project set to Content doesn't get loaded when UseConfiguration and ContentSource is used
Current behavior
Following the new Uno templates I wanted to take advantage of the Uno Extensions Configuration service. The default is to use an embedded configuration file, which works fine, but for my purpose I want it to exist as a file in the deployment. I changed the build action on appsettings.json to Content. In the head I can confirm that it's stored in a subfolder called Shared (after the assembly where the json file resides). But the ContentSource doesn't find it. If I turn on logging then I can see it searches a couple of different folders, not where my app is. Either this is incorrect (bug), or there should be a way to specify the folder where ContentSource should expect the files (enhancement request).
Expected behavior
appsettings.json in Shared project set to Content should be loaded by UseConfiguration
How to reproduce it (as minimally and precisely as possible)
Change build action on appsettings.json to Content, change UseConfiguration to:
.UseConfiguration(configure: configBuilder =>
configBuilder
.ContentSource()
.Section<AppConfig>()
)
Environment
Nuget Package: Uno.Extensions.Configuration
Package Version(s): 2.3.11
Affected platform(s):
- [ ] iOS
- [ ] Android
- [ ] WebAssembly
- [ ] WebAssembly renders for Xamarin.Forms
- [X] Windows
- [X] Linux
Visual Studio:
- [X] 2022
Anything else we need to know?
Tested and confirmed to not work in WinUI, Linux.Framebuffer and Windows.Gtk
@HakanL thanks for posting this - I'll investigate but I'm going to assume that this issue is a result in the change to class library structure. The big caveat to using appsettings as content is that it isn't well supported on wasm - it does work but configuration is reloaded once the file system is available, so not available for reading appsettings during host builder. Since it look like you're not using wasm (from the checked platforms above), you should be good to use Content
You're correct that I'm not using Wasm, I'm working on a solution that will only run on Linux Framebuffer (and WinUI/GTK for development on my PC). Reloading settings from appsettings would be a nice feature to have, but as I reported, because of the class library structure (which I love BTW, Visual Studio was always quite cranky with the shproj type) the appsettings file (set to content) gets put under a subfolder (named after the shared project name). Having a way to to add to the search paths in ContentSource would be one solution.
BTW for me ContentSource() is not working at all. I think hosting environment is null when load the config files
My recommendation is not to use ContentSource. This is on the backlog to investigate but it's never going to be as reliable on all platforms as EmbeddedSource due to the asynchronous file access on some platforms.
I ran into the same issue and spent quite a lot time on figuring out that the configuration mechanism is not working as the API suggested (to me at least). I'm porting a ASP.NET application to Uno.UI and I would like to stick to the existing options implementation. I'm targetting Linux and Windows only. I'm aware that there are restrictions on WASM, but still I would appreciate some more flexibility for none-WASM/Android/... applications. Also, I don't see how embedding appsettings.json is usefull in the first place. May be I'm wrong, but I think embedding the configuration would require re-compiling and deploying the application with each change of the configuration. But enabling configuring the application after deployment is the very purpose of a configuration file like appsettings.json, isn't it?
I digged deeper into the code to figure out how the path to appsettings.json is assembled.
The static method AddConfigurationFile of class ConfigurationBuilderExtensions gets the app data path from the environment of the hosting context. Of course, this is quite straight forward on one hand, but restricting a flexible use of Json files as configuration source on the other hand. It would be greate if I could just pass in the path of the file.
Again, may be I got something wrong and there is another way to accomplish this. Any suggestions are very welcome!
I just found a solution (workaround?):
ConfigureAppConfiguration((context, builder) =>
{
string enviroment = context.HostingEnvironment.EnvironmentName.ToLower();
string filename = enviroment is {Length: > 0} ? $"appsettings.{enviroment}.json" : "appsettings.json";
string basePath = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "/etc/amadea/desk-node/" : "c:\\test";
string absolutePath = Path.Combine(basePath, filename);
builder.AddJsonFile(absolutePath);
)
Maybe there are side effects that I don't see, yet. But it works at least in my use case.