-
Notifications
You must be signed in to change notification settings - Fork 59
Description
Current behavior
- Initially commented on (forgotten?) Issue about
.ContentSource(...)[Configuration] appsettings.json in Shared project set to Content doesn't get loaded when UseConfiguration and ContentSource is used #1497
I am unable to source Solution-wide-synced Configuration or json Data like the <Content Include="..." LinkBase="..." CopyToOutputDirectory="..." /> (used in the Uno.Chefs App with Windows.Storage.StorageFile.* ), with simply using the provided IConfigBuilder.ContentSource Functionallity:
uno.extensions/src/Uno.Extensions.Configuration/ConfigBuilderExtensions.cs
Lines 31 to 54 in 9e1337c
| public static IConfigBuilder ContentSource(this IConfigBuilder hostBuilder, string? config = null, bool includeEnvironmentSettings = true) | |
| { | |
| return hostBuilder | |
| .ConfigureAppConfiguration((ctx, b) => | |
| { | |
| if (config is { Length: > 0 }) | |
| { | |
| b.AddConfiguration(ctx, config); | |
| if (includeEnvironmentSettings) | |
| { | |
| b.AddEnvironmentConfiguration(ctx, config); | |
| } | |
| } | |
| else | |
| { | |
| b.AddAppConfiguration(ctx); | |
| if (includeEnvironmentSettings) | |
| { | |
| b.AddEnvironmentAppConfiguration(ctx); | |
| } | |
| } | |
| }).AsConfigBuilder(); | |
| } | |
The detail that I think is maybe causing the problem, is that as soon as ContentSource for example calls Line 38:
uno.extensions/src/Uno.Extensions.Configuration/ConfigBuilderExtensions.cs
Lines 31 to 53 in 9e1337c
| public static IConfigBuilder ContentSource(this IConfigBuilder hostBuilder, string? config = null, bool includeEnvironmentSettings = true) | |
| { | |
| return hostBuilder | |
| .ConfigureAppConfiguration((ctx, b) => | |
| { | |
| if (config is { Length: > 0 }) | |
| { | |
| b.AddConfiguration(ctx, config); | |
| if (includeEnvironmentSettings) | |
| { | |
| b.AddEnvironmentConfiguration(ctx, config); | |
| } | |
| } | |
| else | |
| { | |
| b.AddAppConfiguration(ctx); | |
| if (includeEnvironmentSettings) | |
| { | |
| b.AddEnvironmentAppConfiguration(ctx); | |
| } | |
| } | |
| }).AsConfigBuilder(); | |
| } |
which can not apply if this ContentSource is something like ../AppData/*.json to load content data, (using LinkBase would then remove the ../) we would end up with something like this in the Chefs App: AppData/Reciepes.json
The ContentSource call then calls:
-
.AddConfiguration(...from here:uno.extensions/src/Uno.Extensions.Configuration/ConfigurationBuilderExtensions.cs
Lines 22 to 34 in 9e1337c
/// <summary> /// Adds a JSON configuration source by name to builder. /// </summary> /// <param name="configurationBuilder">The builder instance used to create an <see cref="IConfiguration"/> with keys and values from a set of sources</param> /// <param name="hostingContext">The <see cref="HostBuilderContext"/> which provides information specific to the hosting environment</param> /// <param name="configurationName">A name to identify the added configuration source. Optional</param> /// <returns>The <see cref="IConfigurationBuilder"/>.</returns> public static IConfigurationBuilder AddConfiguration(this IConfigurationBuilder configurationBuilder, HostBuilderContext hostingContext, string? configurationName = null) { var configSection = configurationName is { Length: > 0 } ? string.Format(AppConfiguration.FileNameTemplate, configurationName) : AppConfiguration.FileName; return configurationBuilder.AddConfigurationFile(hostingContext, configSection.ToLower()); } recognize Line 31:
var configSection = configurationName is { Length: > 0 } ? string.Format(AppConfiguration.FileNameTemplate, configurationName) : AppConfiguration.FileName;`
so in case we provided a Name to ContentSource, this will go into using
string.Format( -
We can find the
AppConfiguration.FileNameTemplateand it's always usedPrefixright here:
https://github.com/unoplatform/uno.extensions/blob/9e1337c5d07679dba1c31a0324a4d9ca5993d45b/src/Uno.Extensions.Configuration/AppConfiguration.cs#L3-L9 -
so resulting from this, the example string value me might provided:
AppData/Reciepes.json -
would now in line 31 of the
AddConfigurationbecome:appsettings.AppData/Reciepes.jsonbecause this is howstring.Formatworks. It fills the numbers you provide starting from{0}. -
Of course, this file name now is not longer what we should be expecting, would be invalid and resulting in not loaded Configuration Data at runtime just the issue linked files for example.
-
Then after AddConfiguration function did made our provided filename/path invalid, we will send it over to the private
.AddConfigurationFile(here:uno.extensions/src/Uno.Extensions.Configuration/ConfigurationBuilderExtensions.cs
Lines 10 to 21 in 9e1337c
private static IConfigurationBuilder AddConfigurationFile(this IConfigurationBuilder configurationBuilder, HostBuilderContext hostingContext, string configurationFileName) { var relativePath = $"{ConfigBuilderExtensions.ConfigurationFolderName}/{configurationFileName}"; var rootFolder = hostingContext.HostingEnvironment.GetAppDataPath(); if (rootFolder is null) { return configurationBuilder; } var fullPath = Path.Combine(rootFolder, relativePath); return configurationBuilder.AddJsonFile(fullPath, optional: true, reloadOnChange: false); } Possibly this might be pointing to a output folder in
/binor/obj(?) but if not, I just want to remark, that theConfigBuilderExtensions.ConfigurationFoldeNameconfigis not known by the consumer so to expect us possibly to have such folder in place, would be obviously not working.
The Docs I found in the Walkthrought about ContentSource are using it with Generic brackets:
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
// NOT RECOMMENDED FOR WEB ASSEMBLY
var appBuilder = this.CreateBuilder(e)
.Configure(
host => host
.UseConfiguration(
builder => builder
.ContentSource<App>()but effectively, the source shows, that there is no generic overload and the ConfigBuilder Implementation itself is not having such method at all
uno.extensions/src/Uno.Extensions.Configuration/ConfigBuilderExtensions.cs
Lines 31 to 32 in 9e1337c
| public static IConfigBuilder ContentSource(this IConfigBuilder hostBuilder, string? config = null, bool includeEnvironmentSettings = true) | |
| { |
Expected behavior
-
It should be working flawless, if there is no information about a not useable state when we include slash or non appsettings prefixed files to ContentSource!
-
if the
ContentSourceprovides thestring configargument, but does not realistically allow anything which is not having this prefix ofappsettings, then we should get made aware of this! -
There should be any validation logic for the provided input string, except from null or not null:
- Check for
null(of course this stays) - Check if it
.Contains('/')or.Contains('\')-> do not use the hardcodedappsettingsPrefix and should potentially also not considerUseEnvironmentSettings! - Check if
.ToLower().StartsWith("appsettings")-> either trim this to use the Prefix and not end up withappsettings.appsettings.xyz.jsonor just use the provided one like in 2.
- Check for
How to reproduce it (as minimally and precisely as possible)
Environment
Nuget Package (s):
Package Version(s):
Affected platform(s):
- All Platforms
- Build tasks
Visual Studio:
- 2019 (version: )
- 2022 (version: )
- Visual Studio Code (version: )
- Rider Windows (version: )
- Rider macOS (version: )
Relevant plugins:
- Resharper (version: )