From ABP Sensei
Provides guidance on ABP Framework settings and features: defining settings, reading values with ISettingProvider/ISettingManager, and using IFeatureChecker for feature toggles.
How this skill is triggered — by the user, by Claude, or both
Slash command
/abp-sensei:abp-settings-featuresThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
User asks about settings, ISettingProvider, ISettingManager, ISettingDefinitionProvider, setting values, features, IFeatureChecker, IFeatureDefinitionProvider, feature toggles, or feature management in ABP Framework.
User asks about settings, ISettingProvider, ISettingManager, ISettingDefinitionProvider, setting values, features, IFeatureChecker, IFeatureDefinitionProvider, feature toggles, or feature management in ABP Framework.
ABP's setting system provides a hierarchical, extensible way to manage configuration values with fallback from user → tenant → global → configuration → default.
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);
}
}
}
defaultValue is a string — all setting values stored as stringsisVisibleToClients: true exposes the value to the browser for conditional UIpublic class MyModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<SettingDefinitionContext>(options =>
{
// Modify identity module settings before they're finalized
});
}
}
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-injectISettingProvider. UseSettingProviderproperty directly.
Settings with isVisibleToClients: true are available via JavaScript:
const layoutType = abp.setting.values['App.UI.LayoutType'];
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) |
In appsettings.json:
{
"Settings": {
"Smtp.EnableSsl": "true",
"Smtp.Port": "587"
}
}
public class MySettingDefinitionProvider : SettingDefinitionProvider
{
public override void Define(ISettingDefinitionContext context)
{
context.Add(
new SettingDefinition(
"Smtp.Password",
defaultValue: "",
isVisibleToClients: false,
isEncrypted: true // Encrypted in storage
)
);
}
}
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>();
});
Custom encryption implementation:
public class MyEncryptionService : ISettingEncryptionService, ITransientDependency
{
public string Decrypt(string encryptedValue) { /* ... */ }
public string Encrypt(string plainValue) { /* ... */ }
}
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
ISettingProviderfor reading only (implements caching). UseISettingManagerfor setting management UIs.
Setting values are cached via distributed cache. Always use ISettingManager to change values — it manages the cache.
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 |
public class CustomSettingProvider : SettingManagementProvider, ITransientDependency
{
public override string Name => "Custom";
public CustomSettingProvider(ISettingManagementStore store)
: base(store) { }
}
Configure<SettingManagementOptions>(options =>
{
options.Providers.Add<CustomSettingProvider>();
});
The module provides default UI for:
Extensible — add custom tabs:
MVC:
public class MySettingGroupViewComponent : AbpSettingManagementViewComponent
{
public IViewComponentResult Invoke()
{
return View("~/Views/Shared/Components/MySettingGroup/Default.cshtml");
}
}
Features are tenant-scoped toggles that enable/disable functionality per tenant. Different from settings — features control what a tenant can use.
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)
)
);
}
}
}
| Type | UI | Use Case |
|---|---|---|
ToggleStringValueType | Checkbox | on/off, enabled/disabled |
FreeTextStringValueType | Textbox | Free text, numbers |
SelectionStringValueType | Dropdown | Select from predefined list |
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" }
}
);
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.
[RequiresFeature("BookStore.PdfReporting")]
public class PdfReportAppService : ApplicationService, IPdfReportAppService
{
public async Task<PdfReportResultDto> GetPdfReportAsync()
{
// Only accessible if feature is enabled
}
}
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"));
}
}
ApplicationServicebase class already hasFeatureCheckerproperty injected.
Features are managed via the Feature Management UI (available with Identity module):
ISettingProvider for reading (caching), ISettingManager for writingisVisibleToClients: true only for settings needed in browserisEncrypted: true for sensitive values (passwords, API keys)App., Smtp., Emailing.defaultValuedisplayName for UI displayToggleStringValueType for simple on/off featuresFreeTextStringValueType with validators for numeric limits[RequiresFeature] attribute for automatic feature checkingisVisibleToClients: false for internal-only featuresdisplayName and description| 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 |
npx claudepluginhub burakdmir/abp-skills --plugin abp-senseiProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.