<ABP framework> function management: manages the functions of the abp framework.
Document directory
Content of this section:
- Introduction
- Function Type
- Boolean Function
- Value Function
- Define features
- Basic Function Attributes
- Other features
- Function level
- Check Function
- Use the RequiresFeature feature
- Notes for RequiresFeature features
- Use IFeatureChecker
- Client
- Function Manager
- A version prompt
Introduction
Most SaaS (Multi-tenant) applications have different feature versions (packages), so you can provide different prices and feature options for tenants (customers ).
A function system is provided to make it easy to use. We can define a function and check whether a function is available to a tenant, and integrate the function system into other ABP concepts (such as authorization and navigation ).
About IFeatureValueStore
The function system uses IFeatureValueStore to obtain the function value. Although you can implement it in your own way, it has been fully implemented in the module-zero project. If it is not implemented, NullFeatureValueStore is used to return null for all functions (in this case, the default function value is used ).
Function Type
There are two basic function types.
Boolean Function
It can be "true" or "false". A function of this type can be enabled or disabled (a version or a tenant ).
Value Function
It can be any value, which saves and obtains a string, and the number is also saved as a string.
For example, our application may be a task management application. Only a limited number of tasks are created in a month. Suppose we have two different versions/packages, one of which allows us to create 1000 tasks each month, however, the other allows us to create 5000 tasks each month. Therefore, this function should be saved as a value type, not simply true/false.
Define features
Before checking the function, define it. A module can inherit the FeatureProvider class to define its own function. Here, a very simple function provider defines three functions:
public class AppFeatureProvider : FeatureProvider{ public override void SetFeatures(IFeatureDefinitionContext context) { var sampleBooleanFeature = context.Create("SampleBooleanFeature", defaultValue: "false"); sampleBooleanFeature.CreateChildFeature("SampleNumericFeature", defaultValue: "10"); context.Create("SampleSelectionFeature", defaultValue: "B"); }}
After creating a feature, we should register it in the PreInitialize method of our module, as shown below:
Configuration.Features.Providers.Add<AppFeatureProvider>();
Basic Function Attributes
A function definition requires at least two attributes:
Name: a unique Name (string), a flag of this function.
DefaultValue: a default value. When we need this function value and cannot obtain it from the current tenant, we need a default value.
Here, we define a Boolean function named "SampleBooleanFeature". The default value is "false" (unavailable ), at the same time, we define two value functions (SampleNumericFeature is defined as a sub-function of SampleBooleanFeature ).
Suggestion: Create a String constant as a function name, which can be used wherever possible to avoid input errors.
Other features
Although the unique name and default value attributes are required, they also have optional attributes that provide detailed control.
- Scope: A FeatureScopes enumeration value. It can be Edition (if this function can only be set to version level), Tenant (if this function can only be set to Tenant level) or All (if the version and tenant can be set, the tenant settings overwrite the version settings ). The default value is All.
- DisplayName: a localized string that displays the name of this function.
- Description: a localized string that displays the detailed Description of this function.
- InputType: a ui input type of this function, which can be defined and can be used when an automatic function screen is created.
- Attribute: the user dictionary of a key-value pair.
Let's take a look at the detailed definition of the above function:
public class AppFeatureProvider : FeatureProvider{ public override void SetFeatures(IFeatureDefinitionContext context) { var sampleBooleanFeature = context.Create( AppFeatures.SampleBooleanFeature, defaultValue: "false", displayName: L("Sample boolean feature"), inputType: new CheckboxInputType() ); sampleBooleanFeature.CreateChildFeature( AppFeatures.SampleNumericFeature, defaultValue: "10", displayName: L("Sample numeric feature"), inputType: new SingleLineStringInputType(new NumericValueValidator(1, 1000000)) ); context.Create( AppFeatures.SampleSelectionFeature, defaultValue: "B", displayName: L("Sample selection feature"), inputType: new ComboboxInputType( new StaticLocalizableComboboxItemSource( new LocalizableComboboxItem("A", L("Selection A")), new LocalizableComboboxItem("B", L("Selection B")), new LocalizableComboboxItem("C", L("Selection C")) ) ) ); } private static ILocalizableString L(string name) { return new LocalizableString(name, AbpZeroTemplateConsts.LocalizationSourceName); }}
Note: The input type definition is not used by the ABP function. When the input function is created, it can be used by the application. The ABP only provides the basic framework to make it easier to use.
Function level
As shown in the preceding example, a function can have sub-functions. A parent function is usually defined as a Boolean function. A child function can be obtained only when the parent function is available. It is not mandatory, but it is recommended that the application handle it with caution.
Check Function
We define a function to check its value in the application to allow or block some application functions for each tenant. There are several different check methods.
Use the RequiresFeature feature
We can use RequiredFeature for a method or class, as shown below:
[RequiresFeature("ExportToExcel")]public async Task<FileDto> GetReportToExcel(...){ ...}
This method can be executed only when the "ExportToExcel" function of the current tenant (obtained from the IAbpSession) is available. If it is unavailable, an AbpAuthorizationException is automatically thrown.
Of course, the RequiresFeature feature should be used for Boolean functions. Otherwise, you will receive an exception.
Notes for RequiresFeature features
For function checks, the following restrictions apply to the use of RequiresFeature in methods:
- It cannot be used in the private method.
- It cannot be used in static methods.
- It cannot be used in methods without injection classes (we must use dependency injection ).
At the same time, it can be used:
- Any public method called through the interface (for example, using the application service through the interface)
- A virtual method called directly by class reference (such as Asp. Net Mvc or Web Api Controller.
- A protected virtual method.
Use IFeatureChecker
We can inject IFeatureChecker and use it to manually check a function (it is automatically injected into the application service, Mvc and Web Api controller and used automatically ).
IsEnabled
Check whether a given function is available, for example:
public async Task<FileDto> GetReportToExcel(...){ if (await FeatureChecker.IsEnabledAsync("ExportToExcel")) { throw new AbpAuthorizationException("You don't have this feature: ExportToExcel"); } ...}
IsEnabledAsync and other methods have the same asynchronous version.
Of course, the IsEnabled method should be used by functions of the Boolean type. Otherwise, you will get an exception.
If you only want to check a function and throw an exception, as shown in the preceding example, you can use the CheckEnabled method.
GetValue
Obtains the current value of the value type function, for example:
var createdTaskCountInThisMonth = GetCreatedTaskCountInThisMonth();if (createdTaskCountInThisMonth >= FeatureChecker.GetValue("MaxTaskCreationLimitPerMonth").To<int>()){ throw new AbpAuthorizationException("You exceed task creation limit for this month, sorry :(");}
The FeatureChecker method also provides the function to work for a specified tenantId, not just for the current tenantId.
Client
On the client side (Javascript), we can use the ABC. features namespace to obtain the current value of the function.
IsEnabled
var isEnabled = abp.features.isEnabled('SampleBooleanFeature');
GetValue
var value = abp.features.getValue('SampleNumericFeature');
Function Manager
If you need to use the function definition, You can inject IFeatureManager and use it.
A version prompt
The ABP framework does not have a version System for the content, because such a system requires a database (storage version, version function, tenant version ing ...), therefore, the version system is implemented in module zero, and you can easily use it and obtain a version system, or implement it yourself.