Base solution for your next web application
Open Closed

Extending ASP Feature Functionality #12269


User avatar
0
JapNolt created

We are looking to extended the abp features functionality by adding our own layer between tenant and edition feature sets. We think there are a few different methods we might be able to override in order to achieve this. We are adding our overrides to this file, which is part of abp. One of which is GetValueOrNullAsync from the AbpFeatureValueStore.cs, although when running our project, this override is not being called.

Is there something we are missing or something else we need to do in order for our override to be called?


9 Answer(s)
  • User Avatar
    0
    m.aliozkaya created
    Support Team

    Hi @JapNolt,

    Did you replace the service in the example below?

    public class MyService : AbpService
    {
    
    }
    

    Then replace in your module:

    public override void PreInitialize()
    {
        Configuration.ReplaceService<IAbpService, MyService>(DependencyLifeStyle.Transient);
    }
    
  • User Avatar
    0
    JapNolt created

    We did try that. We can also replicate in the vanilla project from aspnet zero. Heres what I did there.

    Add this override to the existing aspnet zero class FeatureValueStore:

    public override Task<string> GetValueOrNullAsync(int tenantId, string featureName)
    {
        return base.GetValueOrNullAsync(tenantId, featureName);
    }
    

    Add this to the core module, as like mentioned above:

    Configuration.ReplaceService<IFeatureValueStore, FeatureValueStore>(DependencyLifeStyle.Transient);
    

    The override here never gets hit. I tested by doing the CreateFriendshipWithDifferentTenant api request in the FriendshipAppService which calls for FeatureChecker.IsEnabledAsync.When IsEnabled is called for I would expect my override to get hit. Are we missing something?

  • User Avatar
    0
    m.aliozkaya created
    Support Team

    Hi @JapNolt,

    Sorry for my missing response.

    Go to *.Core project and add this line to PreInitialize method

    Configuration.ReplaceService<IAbpZeroFeatureValueStore, FeatureValueStore>();

    I tested it at editing features of edition. https://localhost:44302/App/Editions

  • User Avatar
    0
    JapNolt created

    We are able to override SetEditionFeatureValueAsync like you have done here. But we aren't able to override the GetValueOrNull in order to add our own layer between editions and tenant settings. Our GetValueOrNull override never gets called.

  • User Avatar
    0
    JapNolt created

    Any ideas on how we can do this?

  • User Avatar
    0
    m.aliozkaya created
    Support Team

    Hi @JapNolt,

    I tested it as seen in the code examples below. I can override GetValueOrNull in both methods. If you share a sample project with me I can check it. [email protected]

    IAbpZeroFeatureValueStore _featureValueStore;
    
    public EditionAppService(
        IAbpZeroFeatureValueStore featureValueStore)
    {
        _featureValueStore = featureValueStore;
    }
    
    private Task SetFeatureValues(Edition edition, List<NameValueDto> featureValues)
    {
        _featureValueStore.GetValueOrNull(1, "TestEditionScopeFeature");
        _featureValueStore.GetValueOrNull(1, new Feature("TestEditionScopeFeature", "TestEditionScopeFeature"));
        
        return _editionManager.SetFeatureValuesAsync(edition.Id,
            featureValues.Select(fv => new NameValue(fv.Name, fv.Value)).ToArray());
    }
    
    using System.Threading.Tasks;
    using Abp.Application.Features;
    using Abp.Domain.Repositories;
    using Abp.Domain.Uow;
    using Abp.MultiTenancy;
    using Abp.Runtime.Caching;
    using PowerToolsTest12277Demo.Authorization.Users;
    using PowerToolsTest12277Demo.MultiTenancy;
    
    namespace PowerToolsTest12277Demo.Editions;
    
    public class FeatureValueStore : AbpFeatureValueStore<Tenant, User>
    {
        public FeatureValueStore(
            ICacheManager cacheManager,
            IRepository<TenantFeatureSetting, long> tenantFeatureSettingRepository,
            IRepository<Tenant> tenantRepository,
            IRepository<EditionFeatureSetting, long> editionFeatureSettingRepository,
            IFeatureManager featureManager,
            IUnitOfWorkManager unitOfWorkManager)
            : base(cacheManager,
                tenantFeatureSettingRepository,
                tenantRepository,
                editionFeatureSettingRepository,
                featureManager,
                unitOfWorkManager)
        {
        }
    
        public override string GetValueOrNull(int tenantId, Feature feature)
        {
            var x = 3;
            return base.GetValueOrNull(tenantId, feature);
        }
        
        public override string GetValueOrNull(int tenantId, string feature)
        {
            var x = 3;
            return base.GetValueOrNull(tenantId, feature);
        }
    
        public override void SetEditionFeatureValue(int editionId, string featureName, string value)
        {
            var y = 3;
            base.SetEditionFeatureValue(editionId, featureName, value);
        }
    
        public override Task SetEditionFeatureValueAsync(int editionId, string featureName, string value)
        {
            var z = 3;
            return base.SetEditionFeatureValueAsync(editionId, featureName, value);
        }
    }
    

    Configuration.ReplaceService<IAbpZeroFeatureValueStore, FeatureValueStore>();

  • User Avatar
    0
    JapNolt created

    We followed the directions you provided above and it seems to partially work. It seems like the overridden methods are called when editing the Edition features and Tenant features.

    Here is a list of items that are still NOT working.

    • Feature caches (edition and tenant) are not being cleared when setting a feature using the overridden methods.
    • FeatureChecker code is not working in the app services (aka. FeatureChecker.IsEnabled). The overridden methods are not getting hit. I assume that the RequiresFeature attribute doesn't work either, although I didn't test that.
    • The GetAll method in AbpUserConfigurationController is not calling the overridden methods. So the Angular client side is receiving incorrect feature values.

    To prove this, we override all the "GetValue" methods in the FeatureValueStore. For a specific feature, AppFeatures.MaxUserCount, we are hard coding the value to "1000".

    • We are then checking this feature value in the GetCountries method of the DemoUiComponentsAppService application service. But it is returning "0" instead of "1000".
    • When looking at Browser Dev Tools and inspecting the GetAll method, "0" is returned instead of "1000".

    We will send a link by email to download our "test" project.

  • User Avatar
    0
    m.aliozkaya created
    Support Team

    Hi @JapNolt,

    Thanks we will check it as soon as possible.

  • User Avatar
    0
    m.aliozkaya created
    Support Team

    Hi @JapNolt,

    We found the problem. You can override feature value stores like this.

    Go to the IdentityRegistrar class. Add .AddFeatureValueStore<FeatureValueStore>().

    Remove Configuration.ReplaceService<IAbpZeroFeatureValueStore, FeatureValueStore>(); from Core Module