Search code examples
c#asp.net-mvcasp.net-coresettingsaspnetboilerplate

How to use SettingDefinitionGroup?


I use the free multi-page template for ASP.NET Core v4.0.0, which is based on the ASP.NET Boilerplate v3.8.1. The template already implements AppSettingProvider, in which you can add the necessary settings for the application or user scope like so on. The problem is that I need to use a very large number of settings, which makes sense to group. To do this, the SettingDefinition class has the SettingDefinitionGroup group property. But how to use it? The official documentation says that this serves just for use in the UI, but does not give an example of its use.

For example, there is such a structure of settings:

namespace ProjectName.Configuration {

    public static class AppSettingNames {

        public const string UiTheme = "App.UiTheme";

        public static class BaseData {
            public static class Company {
                public const string Name = "BaseData.Company.Name";
                // ...
                public static class PostAddress {
                    public const string Country = "BaseData.Company.PostAddress.Country";
                    // ...
                }
            }
            public static class UI {
                public static class Footer {
                    public const bool IsVisible = "BaseData.UI.Footer.IsVisible";
                    // ...
                }
                public static class Widget {
                    public static class Weather {
                        public const bool IsVisible = "BaseData.UI.Widget.IsVisible";
                        // ...
                    }
                }
            }
        }
    }
}

How, in this case, to specify it in the SettingProvider and use setting groups in UI?

namespace ProjectName.Configuration {
    public class AppSettingProvider : SettingProvider {

        public override IEnumerable<SettingDefinition> GetSettingDefinitions(SettingDefinitionProviderContext context) {
            return new[]
            {
                new SettingDefinition(AppSettingNames.UiTheme, 
                    "red", 
                    scopes: SettingScopes.Application | SettingScopes.Tenant | SettingScopes.User, 
                    isVisibleToClients: true
                ),

                /* BaseData */
                new SettingDefinition(AppSettingNames.BaseData.Company.Name,
                    "default value",
                    displayName: "setting name",
                    description: "setting description",
                    scopes: SettingScopes.Application | SettingScopes.Tenant,
                    isVisibleToClients: true,
                    group: ?,
                    clientVisibilityProvider: new RequiresAuthenticationSettingClientVisibilityProvider()
                )
            };
        }
    }
}

Solution

  • It is not currently being used, so there is a little work to do to actually use it.

    Configuration:

    public class AppSettingProvider : SettingProvider
    {
        // Hold groups
        public static List<SettingDefinitionGroup> Groups = new List<SettingDefinitionGroup>();
    
        public override IEnumerable<SettingDefinition> GetSettingDefinitions(SettingDefinitionProviderContext context)
        {
            // Create groups
            var group1 = new SettingDefinitionGroup("group1", new LocalizableString("group1_displayName", "sourceName"));
            var group2 = new SettingDefinitionGroup("group2", new LocalizableString("group2_displayName", "sourceName"));
    
            // Add groups
            Groups.Add(group1);
            Groups.Add(group2);
    
            // Configure hierarchy
            group1.AddChild(group2);
    
            return new[]
            {
                new SettingDefinition(AppSettingNames.UiTheme,
                    "red",
                    scopes: SettingScopes.Application | SettingScopes.Tenant | SettingScopes.User,
                    isVisibleToClients: true
                ),
    
                // Grouped
                new SettingDefinition("setting1_name",
                    "setting1_defaultValue",
                    group: group1
                ),
                new SettingDefinition("setting2_name",
                    "setting2_defaultValue",
                    group: group2
                )
            };
        }
    }
    

    UI model:

    public class SettingGroup
    {
        public List<SettingGroup> Children { get; set; }
    
        public string Name { get; set; }
    
        public List<ISettingValue> Settings { get; set; }
    }
    

    Helpers:

    private async Task<SettingGroup> GetSettingGroup(string name)
    {
        var groupList = AppSettingProvider.Groups.Where(g => g.Name == name).ToList();
        var settingDefinitions = _settingDefinitionManager.GetAllSettingDefinitions();
        var settings = await SettingManager.GetAllSettingValuesAsync();
    
        return GetSettingGroupsRecursively(groupList, settingDefinitions, settings).FirstOrDefault();
    }
    
    private List<SettingGroup> GetSettingGroupsRecursively(IReadOnlyList<SettingDefinitionGroup> groups, IReadOnlyList<SettingDefinition> settingDefinitions, IReadOnlyList<ISettingValue> settings)
    {
        return groups
            .Select(group => new SettingGroup
            {
                Children = GetSettingGroupsRecursively(group.Children, settingDefinitions, settings),
                Name = group.Name,
                Settings = GetGroupSettings(group, settingDefinitions, settings)
            })
            .ToList();
    }
    
    private List<ISettingValue> GetGroupSettings(SettingDefinitionGroup group, IReadOnlyList<SettingDefinition> settingDefinitions, IReadOnlyList<ISettingValue> settings)
    {
        return settingDefinitions
            .Where(sd => sd.Group?.Name == group?.Name)
            .Select(sd => settings.Where(s => s.Name == sd.Name).FirstOrDefault())
            .Where(s => s != null)
            .ToList();
    }
    

    Usage:

    var group1SettingGroup = await GetSettingGroup("group1");
    var group1Settings = group1SettingGroup.Settings;
    
    // Check hierarchy
    // var group2SettingGroup = group1SettingGroup.Children.First();
    // var group2Settings = group2SettingGroup.Settings;