‹ 首页

abp-settings-features

@burakdmir · 收录于 昨天 · 上游提交 2 周前

ABP Framework v10.x (10.4/10.5) settings and features: ISettingProvider/ISettingManager, SettingDefinitionProvider, IFeatureChecker, feature toggle. Use for configuration management, settings, or feature flags in ABP.

适合你,如果正在使用 ABP Framework 开发,需要管理设置和功能开关。

/ 通过 npx 安装 校验哈希
npx oh-my-skill add burakdmir/abp-skills/abp-settings-features
/ 通过 bash 安装
curl -fsSL https://oh-my-skill.com/install.sh | bash -s -- burakdmir/abp-skills/abp-settings-features
/ 已经装过?验证本机副本,不用重装
npx oh-my-skill verify burakdmir/abp-skills/abp-settings-features
安装目标可用 --agent / --scope 或 --to 明确指定;省略时只会在唯一已存在的 agent 目录上自动选择,零命中或多命中会停止并提示。content_hash 缺失或不一致均拒装。
13GitHub stars
~2.1K上下文体积 · 单文件
索引托管

怎么用

商店整理自技能原文 · 版本 ce71259 · 表述以原文为准
它做什么

装好后,Claude 能帮你处理 ABP Framework 的设置和功能开关,包括定义设置、读取设置值、管理用户/租户/全局设置,以及定义功能、检查功能和设置功能值。

什么时候触发

当你询问 ABP 设置或功能开关相关概念、代码或用法时触发,例如提到 ISettingProvider、ISettingManager、IFeatureChecker 等关键词。

装好后可以这样说
演示 IFeatureChecker 用法
技能原文 SKILL.md作者撰写 · MIT · ce71259

ABP Settings & Features Skill

Trigger

User asks about settings, ISettingProvider, ISettingManager, ISettingDefinitionProvider, setting values, features, IFeatureChecker, IFeatureDefinitionProvider, feature toggles, or feature management in ABP Framework.


Part 1: Settings System
Core Concepts

ABP's setting system provides a hierarchical, extensible way to manage configuration values with fallback from user → tenant → global → configuration → default.

Defining Settings

Create a class inheriting SettingDefinitionProvider:

using Volo.Abp.Settings;

namespace Acme.BookStore.Settings
{
    public class BookStoreSettingDefinitionProvider : SettingDefinitionProvider
    {
        public override void Define(ISettingDefinitionContext context)
        {
            context.Add(
                new SettingDefinition(
                    "App.UI.LayoutType",
                    defaultValue: "LeftMenu",
                    displayName: L["LayoutType"],
                    isVisibleToClients: true
                ),
                new SettingDefinition(
                    "Smtp.EnableSsl",
                    defaultValue: "false",
                    displayName: L["EnableSsl"],
                    isVisibleToClients: false
                )
            );
        }

        private static LocalizableString L(string name)
        {
            return LocalizableString.Create<BookStoreResource>(name);
        }
    }
}
  • ABP auto-discovers this class
  • defaultValue is a string — all setting values stored as strings
  • isVisibleToClients: true exposes the value to the browser for conditional UI
Changing Setting Definitions of a Dependent Module
public class MyModule : AbpModule
{
    public override void PreConfigureServices(ServiceConfigurationContext context)
    {
        PreConfigure<SettingDefinitionContext>(options =>
        {
            // Modify identity module settings before they're finalized
        });
    }
}
Reading Setting Values
public class MyService : ITransientDependency
{
    private readonly ISettingProvider _settingProvider;

    public MyService(ISettingProvider settingProvider)
    {
        _settingProvider = settingProvider;
    }

    public async Task FooAsync()
    {
        // Get as string (null if not set)
        string userName = await _settingProvider.GetOrNullAsync("Smtp.UserName");

        // Get as bool, fallback to default
        bool enableSsl = await _settingProvider.GetAsync<bool>("Smtp.EnableSsl");

        // Get as bool, fallback to provided default
        bool enableSsl = await _settingProvider.GetAsync<bool>(
            "Smtp.EnableSsl", defaultValue: true);

        // Shortcut: IsTrueAsync
        bool enableSsl = await _settingProvider.IsTrueAsync("Smtp.EnableSsl");

        // Get as int
        int port = await _settingProvider.GetAsync<int>("Smtp.Port");

        // Get as nullable int
        int? port = (await _settingProvider.GetOrNullAsync("Smtp.Port"))?.To<int>();
    }
}
ApplicationService, DomainService, and other base classes already property-inject ISettingProvider. Use SettingProvider property directly.
Reading on Client Side

Settings with isVisibleToClients: true are available via JavaScript:

const layoutType = abp.setting.values['App.UI.LayoutType'];
Setting Value Providers (Fallback Chain)

5 pre-built providers, evaluated bottom → top:

| Provider | Name | Source | |---|---|---| | DefaultValueSettingValueProvider | "D" | Default value in setting definition | | ConfigurationSettingValueProvider | "C" | IConfiguration (appsettings.json) | | GlobalSettingValueProvider | "G" | System-wide (database) | | TenantSettingValueProvider | "T" | Current tenant (database) | | UserSettingValueProvider | "U" | Current user (database) |

Setting Values in Application Configuration

In appsettings.json:

{
  "Settings": {
    "Smtp.EnableSsl": "true",
    "Smtp.Port": "587"
  }
}
Encrypting Setting Values
public class MySettingDefinitionProvider : SettingDefinitionProvider
{
    public override void Define(ISettingDefinitionContext context)
    {
        context.Add(
            new SettingDefinition(
                "Smtp.Password",
                defaultValue: "",
                isVisibleToClients: false,
                isEncrypted: true  // Encrypted in storage
            )
        );
    }
}
Custom Setting Value Providers
public class CustomSettingValueProvider : SettingValueProvider
{
    public override string Name => "Custom";

    public CustomSettingValueProvider(ISettingStore settingStore)
        : base(settingStore) { }

    public override Task<string> GetOrNullAsync(SettingDefinition setting)
    {
        // Return setting value or null
        // Use SettingStore or another data source
    }
}

// Register
Configure<AbpSettingOptions>(options =>
{
    options.ValueProviders.Add<CustomSettingValueProvider>();
});
ISettingEncryptionService

Custom encryption implementation:

public class MyEncryptionService : ISettingEncryptionService, ITransientDependency
{
    public string Decrypt(string encryptedValue) { /* ... */ }
    public string Encrypt(string plainValue) { /* ... */ }
}

Part 2: Setting Management Module
ISettingManager

Used to get and set setting values (for building setting management UIs):

public class MyService : ITransientDependency
{
    private readonly ISettingManager _settingManager;

    public MyService(ISettingManager settingManager)
    {
        _settingManager = settingManager;
    }

    public async Task FooAsync()
    {
        Guid user1Id = ...;
        Guid tenant1Id = ...;

        // Current user
        string layout = await _settingManager.GetOrNullForCurrentUserAsync("App.UI.LayoutType");
        await _settingManager.SetForCurrentUserAsync("App.UI.LayoutType", "LeftMenu");

        // Specific user
        await _settingManager.SetForUserAsync(user1Id, "App.UI.LayoutType", "LeftMenu");

        // Current tenant
        await _settingManager.SetForCurrentTenantAsync("App.UI.LayoutType", "LeftMenu");

        // Specific tenant
        await _settingManager.SetForTenantAsync(tenant1Id, "App.UI.LayoutType", "LeftMenu");

        // Global
        await _settingManager.SetGlobalAsync("App.UI.LayoutType", "TopMenu");
        string global = await _settingManager.GetOrNullGlobalAsync("App.UI.LayoutType");
    }
}
Use ISettingProvider for reading only (implements caching). Use ISettingManager for setting management UIs.
Setting Cache

Setting values are cached via distributed cache. Always use ISettingManager to change values — it manages the cache.

Setting Management Providers

5 pre-built providers (reverse order execution):

| Provider | Can Get | Can Set | |---|---|---| | DefaultValueSettingManagementProvider | Yes | No | | ConfigurationSettingManagementProvider | Yes | No | | GlobalSettingManagementProvider | Yes | Yes | | TenantSettingManagementProvider | Yes | Yes | | UserSettingManagementProvider | Yes | Yes |

Custom Setting Management Provider
public class CustomSettingProvider : SettingManagementProvider, ITransientDependency
{
    public override string Name => "Custom";

    public CustomSettingProvider(ISettingManagementStore store)
        : base(store) { }
}

Configure<SettingManagementOptions>(options =>
{
    options.Providers.Add<CustomSettingProvider>();
});
Setting Management UI

The module provides default UI for:

  • Email settings (with "Send test email" button)
  • Feature management
  • Timezone settings

Extensible — add custom tabs:

MVC:

public class MySettingGroupViewComponent : AbpSettingManagementViewComponent
{
    public IViewComponentResult Invoke()
    {
        return View("~/Views/Shared/Components/MySettingGroup/Default.cshtml");
    }
}

Part 3: Features System
Core Concepts

Features are tenant-scoped toggles that enable/disable functionality per tenant. Different from settings — features control what a tenant can use.

Defining Features
using Volo.Abp.Features;
using Volo.Abp.Validation.StringValues;

namespace Acme.BookStore.Features
{
    public class BookStoreFeatureDefinitionProvider : FeatureDefinitionProvider
    {
        public override void Define(IFeatureDefinitionContext context)
        {
            var myGroup = context.AddGroup("BookStore");

            // Boolean toggle feature
            myGroup.AddFeature(
                "BookStore.PdfReporting",
                defaultValue: "false",
                displayName: LocalizableString.Create<BookStoreResource>("PdfReporting"),
                valueType: new ToggleStringValueType()
            );

            // Numeric feature with validator
            myGroup.AddFeature(
                "BookStore.MaxProductCount",
                defaultValue: "10",
                displayName: LocalizableString.Create<BookStoreResource>("MaxProductCount"),
                valueType: new FreeTextStringValueType(
                    new NumericValueValidator(0, 1000000)
                )
            );
        }
    }
}
Feature Value Types

| Type | UI | Use Case | |---|---|---| | ToggleStringValueType | Checkbox | on/off, enabled/disabled | | FreeTextStringValueType | Textbox | Free text, numbers | | SelectionStringValueType | Dropdown | Select from predefined list |

Other Feature Properties
myGroup.AddFeature(
    "BookStore.Advanced",
    defaultValue: "false",
    displayName: L["AdvancedFeature"],
    description: L["AdvancedFeatureDescription"],
    valueType: new ToggleStringValueType(),
    isVisibleToClients: true,  // Expose to browser (default: true)
    properties: new Dictionary<string, object>
    {
        { "CustomProperty", "value" }
    }
);
Child Features
var reporting = myGroup.AddFeature(
    "BookStore.Reporting",
    defaultValue: "false",
    displayName: L["Reporting"],
    valueType: new ToggleStringValueType()
);

reporting.AddChild(
    "BookStore.PdfExport",
    defaultValue: "false",
    displayName: L["PdfExport"],
    valueType: new ToggleStringValueType()
);

Child features only available when parent is enabled.

Checking Features
RequiresFeature Attribute
[RequiresFeature("BookStore.PdfReporting")]
public class PdfReportAppService : ApplicationService, IPdfReportAppService
{
    public async Task<PdfReportResultDto> GetPdfReportAsync()
    {
        // Only accessible if feature is enabled
    }
}
IFeatureChecker Service
public class ReportingAppService : ApplicationService
{
    public async Task DoWorkAsync()
    {
        // Check if enabled
        if (await FeatureChecker.IsEnabledAsync("BookStore.PdfReporting"))
        {
            // Feature is enabled
        }

        // Get value
        string maxCount = await FeatureChecker.GetOrNullAsync("BookStore.MaxProductCount");

        // Extension methods
        bool isEnabled = await FeatureChecker.IsTrueAsync("BookStore.PdfReporting");
        int max = (await FeatureChecker.GetAsync<int>("BookStore.MaxProductCount"));
    }
}
ApplicationService base class already has FeatureChecker property injected.
Feature Management Modal

Features are managed via the Feature Management UI (available with Identity module):

  • Shown per-tenant
  • Toggle features on/off
  • Set feature values
  • Child features shown nested under parent

Best Practices
Settings
  1. Use ISettingProvider for reading (caching), ISettingManager for writing
  2. Set isVisibleToClients: true only for settings needed in browser
  3. Use isEncrypted: true for sensitive values (passwords, API keys)
  4. Group settings with prefixes: App., Smtp., Emailing.
  5. Always provide sensible defaultValue
  6. Localize displayName for UI display
Features
  1. Use features for tenant-scoped functionality toggles
  2. Use ToggleStringValueType for simple on/off features
  3. Use FreeTextStringValueType with validators for numeric limits
  4. Use child features for dependent functionality
  5. Use [RequiresFeature] attribute for automatic feature checking
  6. Set isVisibleToClients: false for internal-only features
  7. Localize feature displayName and description

Settings vs Features

| Aspect | Settings | Features | |---|---|---| | Purpose | Configuration values | Functionality toggles | | Scope | User, Tenant, Global | Tenant only | | Value types | Any string | Toggle, FreeText, Selection | | UI | Setting Management page | Feature Management modal | | Fallback | 5-level chain | Default value only | | Encryption | Supported | Not typically needed | | Client access | isVisibleToClients | isVisibleToClients |


Related
按 MIT 许可原样转载,未经改动 · 在 GitHub 查看 →

评论

登录即可评论;带「已验证安装」的,是发布者名下有本店的安装或持有记录。