Open Closed

WithProviders("T") - feature still shown in Edition Features UI #10684


User avatar
0
papusa created

n ABP 10.1.1, a feature defined with .WithProviders(TenantFeatureValueProvider.ProviderName) still appears in the SaaS Edition Features dialog and can be saved for provider E. However, runtime IFeatureChecker appears to filter value providers by FeatureDefinition.AllowedProviders, so edition values for that feature are ignored and only tenant values are considered.

Could you clarify whether AllowedProviders is intended to restrict only runtime feature value providers, or also Feature Management UI/API providers? If it is runtime-only, should the Edition Features dialog hide or disable features whose AllowedProviders does not include E, to avoid saving values that runtime checks will not use?

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

9 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • AllowedProviders (set via WithProviders(...)) is intended to restrict which value providers are considered at runtime for that feature. So in your example, if the feature only allows TenantFeatureValueProvider.ProviderName (“T”), then IFeatureChecker will ignore the edition (“E”) value even if one exists, and only tenant/default can take effect.
    • In ABP 10.1.1, the Feature Management UI/API (including the SaaS Edition Features dialog) does not automatically hide/disable features based on FeatureDefinition.AllowedProviders. As a result, it can still let you save an edition-level value that will never be used at runtime for that feature. This is essentially a UX mismatch: the stored value is valid data, but it is not applicable given the feature definition’s allowed providers.

    What you should do to avoid the “configurable but ignored” situation:

    1. Preferred (keep behavior consistent): allow “E” if you want it configurable in Edition Features
    context.AddGroup("MyGroup")
        .AddFeature("MyFeature",
            defaultValue: "false")
        .WithProviders(
            TenantFeatureValueProvider.ProviderName,
            EditionFeatureValueProvider.ProviderName
        );
    
    1. If you intentionally want tenant-only configuration, then you should treat edition configuration as irrelevant and (today) you must enforce that at the UI layer yourself:
    • Customize/extend the Feature Management UI so that when editing an Edition you filter out (or disable) any feature whose AllowedProviders does not include "E".

    No verified source available for this specific UI behavior detail in ABP 10.1.1 (the runtime provider filtering is consistent with the feature system’s “Feature Value Providers executed one by one” design, but the “Edition Features dialog should hide/disable based on AllowedProviders” behavior is not documented/guaranteed).


    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    papusa created

    I would consider this a bug, not only a UX mismatch. If AllowedProviders = ["T"], the Edition Features UI should not allow saving an "E" value that runtime feature checking will ignore. The UI/API should respect FeatureDefinition.AllowedProviders for the provider currently being edited.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Thanks for the report — you're right, this is a framework-level bug. The Feature Management UI/API should respect FeatureDefinition.AllowedProviders to match the runtime behavior in IFeatureChecker. We'll fix it in the next version: https://github.com/abpframework/abp/pull/25462

    For now, you can work around it on the backend by overriding FeatureAppService.GetAsync to filter features whose AllowedProviders does not include the current providerName. Add this class to your HttpApi.Host project:

    using Microsoft.Extensions.Options;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.Features;
    using Volo.Abp.FeatureManagement;
    
    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(IFeatureAppService))]
    public class MyFeatureAppService : FeatureAppService
    {
        public MyFeatureAppService(
            IFeatureManager featureManager,
            IFeatureDefinitionManager featureDefinitionManager,
            IOptions<FeatureManagementOptions> options)
            : base(featureManager, featureDefinitionManager, options)
        {
        }
    
        public override async Task<GetFeatureListResultDto> GetAsync(string providerName, string providerKey)
        {
            var result = await base.GetAsync(providerName, providerKey);
    
            foreach (var group in result.Groups)
            {
                var filtered = new List<FeatureDto>();
                foreach (var feature in group.Features)
                {
                    var definition = await FeatureDefinitionManager.GetAsync(feature.Name);
                    if (!definition.AllowedProviders.Any() || definition.AllowedProviders.Contains(providerName))
                    {
                        filtered.Add(feature);
                    }
                }
                group.Features = filtered;
            }
    
            return result;
        }
    }
    

    The Edition Features dialog will then hide features that are restricted to other providers.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    papusa created

    Thank you!

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Your question ticket has been refunded.

    Thanks.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    papusa created

    There are no providers on feature groups, only on individual features. However, after filtering out features that are not valid for the current provider, a group can become empty and still be shown in the UI.

    I think that is also an issue: empty feature groups should be hidden after provider-based feature filtering. Just for your information, I have already fixed this on my side within my FeatureAppService replacement.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Good catch — the post-process workaround needs to drop empty groups after filtering, otherwise a group whose features are all restricted to other providers stays in the result with an empty list. Here is the updated snippet:

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(IFeatureAppService))]
    public class MyFeatureAppService : FeatureAppService
    {
        public MyFeatureAppService(
            IFeatureManager featureManager,
            IFeatureDefinitionManager featureDefinitionManager,
            IOptions<FeatureManagementOptions> options)
            : base(featureManager, featureDefinitionManager, options)
        {
        }
    
        public override async Task<GetFeatureListResultDto> GetAsync(string providerName, string providerKey)
        {
            var result = await base.GetAsync(providerName, providerKey);
    
            foreach (var group in result.Groups)
            {
                var filtered = new List<FeatureDto>();
                foreach (var feature in group.Features)
                {
                    var definition = await FeatureDefinitionManager.GetAsync(feature.Name);
                    if (!definition.AllowedProviders.Any() || definition.AllowedProviders.Contains(providerName))
                    {
                        filtered.Add(feature);
                    }
                }
                group.Features = filtered;
            }
    
            result.Groups = result.Groups.Where(g => g.Features.Any()).ToList();
    
            return result;
        }
    }
    

    The framework fix in https://github.com/abpframework/abp/pull/25462 filters inline during enumeration, so the existing empty-group check in FeatureAppService.GetAsync already handles this — once you upgrade you can drop the override.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    papusa created

    Thank you!

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    : )

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on September 16, 2026, 14:50
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.