8, Add settings management for the module in Abp Vnext

In the project, we need to configure some parameters, usually using the aspnetcore configuration system through Appsettings JSON to store configuration parameters; Abp framework contains a set of perfect device management module, which can be used to easily obtain and set the settings of application programs.

The five preset settings management providers in the Abp settings management module are

  • DefaultValueSettingManagementProvider: gets the value from the default value of the setting definition. The default value cannot be changed because it is hard coded on the setting definition
  • ConfigurationSettingManagementProvider: from IConfiguration service Get value from The configuration value cannot be changed because the configuration value cannot be changed at run time
  • GlobalSettingManagementProvider: gets or sets the global (system wide) value of the setting
  • TenantSettingManagementProvider: gets or sets the setting value of the tenant
  • UserSettingManagementProvider: gets or sets the setting value of the user

The following graphically shows the model for setting and obtaining values between five settings

You can also extend your own settings provider, such as the organization's settings management provider, which should be placed between tenants and users.

The following is an example of the source code of the previous chapter to introduce how to add setting management for the file management module.

1. Add settings definition

The so-called DDD domain driver is designed from the domain layer. Whether it is the file management module in the previous chapter or the setting management here, it starts from the domain and extends step by step until the front-end page

Find the Domain project of file management, and in the Settings directory, filemanagementsettings CS to add a constant to set the Key

    public static class FileManagementSettings
    {
        public const string GroupName = "FileManagement";
        // File size allowed to upload
        public const string MaxUploadFileSize = GroupName + ".MaxUploadFileSize";
        // User storage space
        public const string UserStorageSize = GroupName + ".UserStorageSize";
    }

In filemanagementsettingdefinitionprovider Add setting definitions to the CS file

using MyCompany.FileManagement.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Settings;

namespace MyCompany.FileManagement.Settings
{
    public class FileManagementSettingDefinitionProvider : SettingDefinitionProvider
    {
        public override void Define(ISettingDefinitionContext context)
        {
            context.Add(
                new SettingDefinition(
                     FileManagementSettings.MaxUploadFileSize,
                     "1048576", // Default value
                     L("MaxUploadFileSize:Display"), // Display value
                     L("MaxUploadFileSize:Desc"),   // describe
                     true)); // Is it visible to the client

            context.Add(
                new SettingDefinition(
                    FileManagementSettings.UserStorageSize,
                    "1073741824",
                    L("UserStorageSize:Display"),
                    L("UserStorageSize:Desc"),
                    true));
        }
        // Language localization
        private static LocalizableString L(string name)
        {
            return LocalizableString.Create<FileManagementResource>(name);
        }
    }
}

After doing so, the settings have taken effect. Start httpapi Host, enter in the browser https://localhost:44358/api/abp/application-configuration , check the application configuration. Find the Settings configuration section below to find the Settings just defined:

2. ConfigurationSetting

Open the Appsettings of the startup project JSON file, add the file management configuration as follows:

  "Settings": {
    "FileManagement.MaxUploadFileSize": 1000000,
    "FileManagement.UserStorageSize":  200000000
  }

Restart httpapi Host project, review the application configuration again and find that the value of the setting has changed

For the settings of other settings providers, you need to design the application service layer

3. Application service layer design

For the setting management function module, its infrastructure has been implemented in the Abp framework, and dependencies have been added in the startup project; Therefore, there is no need to care about how to design database entities and store data. You can directly inject the ISettingManager interface provided by it to realize the functions of the application service layer

First, in application Add data transfer object DTO and service interface in contracts project:

FileManagementSettingsDto.cs

namespace MyCompany.FileManagement.Settings
{
    public class FileManagementSettingsDto
    {
        public long MaxUploadFileSize { get; set; }

        public long UserStorageSize { get; set; }
    }
}

IFileManagementSettingsService.cs

using System.Threading.Tasks;
using Volo.Abp.Application.Services;

namespace MyCompany.FileManagement.Settings
{
    public interface IFileManagementSettingsService : IApplicationService
    {
        Task<FileManagementSettingsDto> GetAsync();

        Task UpdateAsync(FileManagementSettingsDto input);
    }
}

Then implement the setting management application service

Add Volo. In the Application project Abp. SettingManagement. Reference to Application package

Add filemanagementsettingsservice cs

using Microsoft.AspNetCore.Authorization;
using MyCompany.FileManagement.Permissions;
using MyCompany.FileManagement.Settings;
using System;
using System.Threading.Tasks;
using Volo.Abp.SettingManagement;


namespace MyCompany.FileManagement.Services
{
    [Authorize(FileManagementPermissions.Settings.Default)]
    public class FileManagementSettingsService : FileManagementAppService, IFileManagementSettingsService
    {
        private readonly ISettingManager _settingManager;

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

        public virtual async Task<FileManagementSettingsDto> GetAsync()
        {
            return new FileManagementSettingsDto
            {
                // User settings
                MaxUploadFileSize = Convert.ToInt64(await _settingManager.GetOrNullForCurrentUserAsync(FileManagementSettings.MaxUploadFileSize)),
                // Global settings
                UserStorageSize = Convert.ToInt64(await _settingManager.GetOrNullGlobalAsync(FileManagementSettings.UserStorageSize)),
            };
        }

        public virtual async Task UpdateAsync(FileManagementSettingsDto input)
        {
            await _settingManager.SetForCurrentUserAsync(FileManagementSettings.MaxUploadFileSize, input.MaxUploadFileSize.ToString());
            await _settingManager.SetGlobalAsync(FileManagementSettings.UserStorageSize, input.UserStorageSize.ToString());
        }
    }
}

Finally, add the permission definition. Note that here we put the setting menu item of the file management module under the permission menu of the setting management of the framework. Therefore, it needs to be in application Add Volo. In the contracts project Abp. SettingManagement. Application. References to contracts package

In filemanagementpermissions Add constant to CS

...
using Volo.Abp.SettingManagement;

namespace MyCompany.FileManagement.Permissions
{
    public class FileManagementPermissions
    {
        ...
        ...

        public static class Settings
        {
            public const string Default = SettingManagementPermissions.GroupName + ".FileManagement";
        }
    }
}

Add a permission definition in FileManagementPermissionDefinitionProvider

...
using Volo.Abp.SettingManagement;

namespace MyCompany.FileManagement.Permissions
{
    public class FileManagementPermissionDefinitionProvider : PermissionDefinitionProvider
    {
        public override void Define(IPermissionDefinitionContext context)
        {
            ...
            // Gets the settings management permission group for the framework
            var settingGroup = context.GetGroup(SettingManagementPermissions.GroupName);
            // Add file management permissions to the set management permissions group
            settingGroup.AddPermission(FileManagementPermissions.Settings.Default, L("Menu:FileManagement"));
        }
        ...
    }
}

Start the front and rear projects, log in and enter the role management page to view the admin role permissions, as shown in the figure:

You can see that file management permission is available in settings management. Check it and save it

4. Add WebApi controller

The Abp framework supports the automatic generation of webapi controllers from the Application service. Here, like file management, we create our own api controllers and add filemanagementsettingscontroller in HttpApi cs

using Microsoft.AspNetCore.Mvc;
using MyCompany.FileManagement.Settings;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;

namespace MyCompany.FileManagement
{
    [RemoteService(Name = FileManagementRemoteServiceConsts.RemoteServiceName)]
    [Area(FileManagementRemoteServiceConsts.ModuleName)]
    [Route("api/file-management/settings")]
    public class FileManagementSettingsController : AbpController, IFileManagementSettingsService
    {
        protected IFileManagementSettingsService _fileManagementSettingsService { get; }

        public FileManagementSettingsController(IFileManagementSettingsService fileManagementSettingsService)
        {
            _fileManagementSettingsService = fileManagementSettingsService;
        }
        [HttpGet]
        public Task<FileManagementSettingsDto> GetAsync()
        {
            return _fileManagementSettingsService.GetAsync();
        }
        [HttpPut]
        public Task UpdateAsync(FileManagementSettingsDto input)
        {
            return _fileManagementSettingsService.UpdateAsync(input);
        }
    }
}

5. Configure angular settings menu and components

The angular setting component collects the setting methods of each module through the SettingTabsService service, and then displays them through the setting menu and Tab page.

First, add the file management setting interface component in the config sub module of file management, because the config sub module is added manually. Before adding components using angular cli, you need to add components in angular Configure config sub module in JSON:

    "file-management": {
      ...
      ...
    },
    "file-management-config": {
      "projectType": "library",
      "root": "projects/file-management/config",
      "sourceRoot": "projects/file-management/config/src",
      "prefix": ""
    }

The project name of the sub module is defined as file management config, so you can add components in the terminal execution statement:

ng generate component file-management-settings-group --skip-tests --project file-management-config

Then add setting - tab. In the providers directory provider. TS, as follows:

import { SettingTabsService } from '@abp/ng.setting-management/config';
import { APP_INITIALIZER } from '@angular/core';
import { FileManagementSettingsGroupComponent } from '../lib/file-management-settings-group/file-management-settings-group.component';

export const FILE_MANAGE_SETTING_TAB_PROVIDERS = [
  {
    provide: APP_INITIALIZER,
    useFactory: configureSettingTabs,
    deps: [SettingTabsService],
    multi: true,
  },
];

export function configureSettingTabs(settingTabs: SettingTabsService) {
  return () => {
    settingTabs.add([
      {
        name: 'FileManagement::Menu:FileManagement',
        order: 50,
        requiredPolicy: 'SettingManagement.FileManagement',
        component: FileManagementSettingsGroupComponent,
      },
    ]);
  };
}

Including APP_INITIALIZER is an injectable token of InjectionToken type. The value it can receive is a method group. In these methods, the program can be configured, and file in the code_ MANAGE_ SETTING_ TAB_ Providers will set settingtabs add(...) The method is encapsulated as the configureSettingTabs method and provided to APP_INITIALIZER, other modules may also have this setting tab Providers, they will provide the root module with the forRoot() method of the module for initialization, and inject app anywhere in the program_ The initializer can get the configuration methods provided in all places

Modify file management config module. TS file, add file in forRoot()_ MANAGE_ SETTING_ TAB_ PROVIDERS

Execute yarn build:files to compile the file module, and then start npm start

You can see that the settings page has taken effect

6. Generate an angular service agent

You can directly run ABP generate proxy - t ng - M filemanagement - a filemanagement -- target file management config to generate the client proxy code to the config sub module, but in this way, the file management main module and config sub module have the same client proxy code, and config cannot reference the methods in the main module;

There are two ways to solve this problem. The first is to create a proxy sub module in the file module, so that both the main module and the config sub module can reference the proxy sub module; The second method is to modify the Area attribute modification of the back-end webapi controller and generate the proxy instruction -m, which is also replaced by the value of the Area attribute modification

Here, we use the second method to modify the Area property of FileManagementSettingsController. The modified value is fileManagementConfig

    [Area("fileManagementConfig")]
    ...
    public class FileManagementSettingsController : AbpController, IFileManagementSettingsService

Restart the backend Host project

Generate the client agent again (note that the method of generating the agent by ABP cli after the latest version upgrade is somewhat different):

abp generate-proxy -t ng -m fileManagementConfig -a FileManagement --target file-management-config

7. Write file setup component code

Modify file management settings group component. HTML, as follows:

<h2>{{ 'FileManagement::Menu:FileManagement' | abpLocalization }}</h2>

<hr class="my-3" />

<form *ngIf="form" [formGroup]="form" (ngSubmit)="submit()" validateOnSubmit>
    <div class="mb-3">
        <label class="form-label" for="max-upload-size">{{ 'FileManagement::MaxUploadFileSize:Display' | abpLocalization }}</label>
        <input type="number" id="max-upload-size" class="form-control" formControlName="maxUploadFileSize" />
    </div>

    <div class="mb-3">
        <label class="form-label" for="user-storage-size">{{ 'FileManagement::UserStorageSize:Display' | abpLocalization
            }}</label>
        <input type="number" id="user-storage-size" class="form-control" formControlName="userStorageSize" />
    </div>

    <hr />

    <button type="submit" [disabled]="saving" class="btn btn-primary">
        <i class="ms-1" [ngClass]="{'fa fa-save': !saving, 'fa fa-spinner fa-spin': saving}"></i>
        {{ 'FileManagement::Files:Save' | abpLocalization }}
    </button>
</form>

Modify file management settings group component. TS, as follows:

import { ToasterService } from '@abp/ng.theme.shared';
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { finalize } from 'rxjs/operators';
import { FileManagementSettingsService } from '../proxy';
import { FileManagementSettingsDto } from '../proxy/settings';

@Component({
  selector: 'lib-file-management-settings-group',
  templateUrl: './file-management-settings-group.component.html',
  styleUrls: ['./file-management-settings-group.component.css']
})
export class FileManagementSettingsGroupComponent implements OnInit {
  form: FormGroup;
  selected: FileManagementSettingsDto;
  saving = false;
  constructor(
    private filesSettingsService: FileManagementSettingsService,
    private toasterService: ToasterService,
    protected fb: FormBuilder,
  ) { }

  ngOnInit(): void {
    this.getData();
  }

  private getData() {
    this.filesSettingsService.get().subscribe(res => {
      this.buildForm(res);
    });
  }

  private buildForm(filesSettings: FileManagementSettingsDto) {
    this.selected = filesSettings;
    this.form = this.fb.group({
      maxUploadFileSize: [filesSettings.maxUploadFileSize, [Validators.required]],
      userStorageSize: [filesSettings.userStorageSize, [Validators.required]],
    });
  }

  submit() {
    if (this.saving || this.form.invalid) { return; }

    this.saving = true;
    this.filesSettingsService
      .update(this.form.value)
      .pipe(finalize(() => (this.saving = false)))
      .subscribe(() => {
        this.toasterService.success('AbpSettingManagement::SuccessfullySaved');
        this.getData();
      });
  }

}

8. Add localized language resources

In the background domain Add multilingual resources to shared

    "MaxUploadFileSize:Display": "Upload file size limit",
    "MaxUploadFileSize:Desc": "Maximum file size allowed to upload (unit) KB). ",
    "UserStorageSize:Display": "User storage space",
    "UserStorageSize:Desc": "The amount of file storage space owned by each user."

Restart the background Host project,

Execute yarn build:files in angular to compile the file module, and then start npm start. The interface is as follows:

Modify the setting value and click save

9. Get the setting value in the angular front end

Previously, we can modify the file upload size limit and user storage space by setting. How can I obtain the setting value? For example, judge the size limit of uploaded files before submitting files to the background

Open the UploadFilesComponent component in the file management module and inject the ConfigStateService service service. The modifications are as follows:

constructor(
    ...
    private toastService: ToasterService,
    private config: ConfigStateService,
    ...) {
      // Get upload size limit settings
      const maxFileSize = this.config.getOne('setting').values['FileManagement.MaxUploadFileSize'];
    this.options = {
      concurrency: 1,
      maxUploads: 3,
      maxFileSize: maxFileSize // Upload file size limit
    };
    ...
  }

Re execute yarn build:files to compile the file module, and then start npm start. It is found that the upload is intercepted when it exceeds 1M

10. Get the setting value at the back end

Open the FileManagementManager file of the file module Domain project and inject the ISettingProvider service to obtain the setting value. The modifications are as follows:

using MyCompany.FileManagement.Settings;
...

namespace MyCompany.FileManagement
{
    public class FileManagementManager: DomainService
    {
        ...
        // Injection setup program interface
        private readonly ISettingProvider _settingProvider;

        public FileManagementManager(...
            ISettingProvider settingProvider)
        {
            ...
            _settingProvider = settingProvider;
        }

        ...
        public async Task<string> CreateAsync(...)
        {
            // Gets the setting value of the user's storage space limit
            var userStorageLimit = await _settingProvider.GetAsync<int>(FileManagementSettings.UserStorageSize);
            // Gets the current used user space size
            var userUsedSize = await _fileRepository.GetStorageSizeAsync(userId);
            var userTotalSize = bytes.Length + userUsedSize;
            if (userTotalSize > userStorageLimit)
            {
                throw new UserFriendlyException("Insufficient space left!");
            }

11. Verify user's configuration

Before saving the settings in the Application service, the user storage space is stored as the global setting, while the upload file size limit is stored as the user setting. Open the file management setting page, modify the setting value, then add a new user, set the permissions, switch to the new user login and view the file management setting page, It is found that the upload file size limit set by the user changes to the configured value of 1000000, while the global setting user storage space is the same as the value in the admin user

Source code of this article: Abp5.0.0 file management module

Tags: abp angular aspnetcore

Posted by jawaking00 on Sun, 19 Dec 2021 00:28:13 +1030