Activities of "alexander.nikonov"

Hi.

I see. I have commented the styles - which appeared to be bootstrap styles - but the layout has not changed. I see no some size overrides from our styles.

I am giving up.

I suggest to close this ticket, but to restore the points for it, because the suitable solution has not been found.

Thank you for your time.

Hi.

Is there a way to get access to 'abp-page' markup - let's say add a class or directive to it - without replacing the components inside it (which makes no sense, because it is not the behavior or data we need to affect)?

We already use our custom directive to calculate the scrolling dynamically for the given selector for our pages:

Probably the easiest and the most reliable thing to resolve a scrolling issue would be making the same thing for any ABP page:

Another question: is it OK that there are nested router outlets - ours and yours - in ABP pages (highlighted in the screenshot above)? If - no, if there a way to fix that?

Hi.

Overriding the "wrapper" could be a solution. Though, the perspective of doing it for several pages does not sound very prominent. For instance, here there is no any external component, still the page does not fit vertically a visible window area: And I have not checked other pages yet.

My theory is that the visible window sizes on ABP pages are somehow calculated incorrectly. So, instead of applying 'patches' to every page, I suggest we determine the root cause.

P.S. Please inform your site support team regarding this very page loading in desktop browser - it's very slow each time due to numerous slow API requests (it does not occur each time - the problem is usually observed at "cold start" - when I open this page every day for the first time).

Hi. Here are the dependencies:

"dependencies": { "@abp/ng.components": "~9.2.4", "@abp/ng.core": "~9.2.4", "@abp/ng.feature-management": "~9.2.4", "@abp/ng.oauth": "~9.2.4", "@abp/ng.permission-management": "~9.2.4", "@abp/ng.setting-management": "~9.2.4", "@abp/ng.theme.shared": "~9.2.4", "@our_lib/base-components": "~19.46.2", "@our_lib/our_lib-abp-common": "^2.0.6", "@our_lib/our_lib-abp-helper": "^2.0.2", "@our_lib/our_lib-components": "^2.0.8", "@our_lib/our_lib-control-config": "^2.0.0", "@our_lib/our_lib-ct-audit-log": "^2.0.5", "@our_lib/our_lib-ct-batch": "^2.0.2", "@our_lib/our_lib-ct-batch-invocation": "^2.0.0", "@our_lib/our_lib-ct-list-spool": "^2.0.4", "@our_lib/our_lib-ct-query-builder": "^2.0.5", "@our_lib/our_lib-ct-reminders": "^2.0.2", "@our_lib/our_lib-dictionary": "^2.0.0", "@our_lib/our_lib-localization": "^2.0.0", "@our_lib/our_lib-modal-window-router-abstractions": "^2.0.0", "@our_lib/our_lib-modal-window-router-bootstrap": "^2.0.0", "@our_lib/our_lib-module-permission": "^2.0.0", "@our_lib/our_lib-report-builder": "^2.0.0", "@our_lib/our_lib-router-outlet": "^2.0.0", "@our_lib/our_lib-utils": "^2.0.0", "@our_lib/our-theme-epsilon": "^2.0.8", "@our_lib/ngb-date-parser-formatter": "^2.0.1", "@agentepsilon/decko": "^2.0.1", "@angular/animations": "~19.2.15", "@angular/cdk": "~19.2.19", "@angular/cdk-experimental": "~19.2.19", "@angular/common": "~19.2.15", "@angular/compiler": "~19.2.15", "@angular/core": "~19.2.15", "@angular/forms": "~19.2.15", "@angular/localize": "~19.2.15", "@angular/material": "~19.2.19", "@angular/material-moment-adapter": "~19.2.19", "@angular/platform-browser": "~19.2.15", "@angular/platform-browser-dynamic": "~19.2.15", "@angular/router": "~19.2.15", "@ctrl/tinycolor": "^4.1.0", "@kolkov/angular-editor": "^2.1.0", "@ng-bootstrap/ng-bootstrap": "~18.0.0", "@ng-select/ng-select": "~14.9.0", "@ngx-dropzone/cdk": "~19.2.1", "@ngx-dropzone/material": "~19.2.1", "@ngxs/router-plugin": "~19.0.0", "@swimlane/ngx-charts": "^22.0.0", "@volo/abp.commercial.ng.ui": "~9.2.4", "@volo/abp.ng.account": "~9.2.4", "@volo/abp.ng.audit-logging": "~9.2.4", "@volo/abp.ng.identity": "~9.2.4", "@volo/abp.ng.language-management": "~9.2.4", "@volo/abp.ng.openiddictpro": "~9.2.4", "@volo/abp.ng.saas": "~9.2.4", "@volo/abp.ng.text-template-management": "~9.2.4", "angular-calendar": "0.31.1", "core-js": "~3.45.1", "date-fns": "^4.1.0", "material-design-icons": "^3.0.1", "moment": "^2.30.1", "ng-zorro-antd": "^19.3.1", "ngx-color-picker": "~19.0.0", "ngx-mask": "^19.0.7", "ngx-moment": "^6.0.2", "normalize.css": "~8.0.1", "rxjs": "~7.8.1", "snq": "^2.0.0", "tslib": "^2.6.3", "uuid": "~13.0.0", "zone.js": "~0.15.1" },

BTW, this very page gets loaded superslow in Windows browser. Could you please inform the team responsible for this site support? I have sent the message to info@abp.io a week ago or more, but no reaction followed:

So, from your screenshot I can see that the grid columns are not resized, instead, a horizontal scrolling appears. But anyway: I have tried patching datatable component behavior without luck: the scrollbars do not appear and the grid (and thus the page) content is drawn overflown across the window visible area in both directions.

Maybe the described problem is related to the fact that we are using our "theme"? But we still need to make ABP page be rendered properly:

I have no access to ABP components (and the components inside this page) directly. I have tried to use a service to modify abp-page markup, but I cannot 'fight' recalculate method of datatable component which is obviously invoked, besides, I do not think it's a proper way to resolve the issue.

Never mind - the change was actually tiny: using "imports: [ThemeSharedModule, CoreModule]," instead of "imports: [LoaderBarComponent, DynamicLayoutComponent, GdprCookieConsentComponent]" (which obviously is not yet supported in our ABP version). Now it does work and there are no API request duplicates. So the reason was inconsistency between a migrated version, but old app.module.ts-ish structure of the project. Thank you for the test project - I will save in for the next upgrade, when we will be on Angular 20 :-D

Thank you. But there are some discrepancies between Angular 19 (we are using in ABP framework 9.2.4) and Angular 20 in your test project. I am trying to convert our front-end to "your" structure (app.module.ts-LESS), but I cannot do that.

Hi.

The custom code was present in our solution, not in ABP test solution. Since it was my only guess why I might get a cancelled ABP app configuration request - I tried to comment the custom app configuration handler. But the error is still there.

As for ABP test solution, as I mentioned - I cannot run it due to some errors. Could you please have a look at the 7z archive and make it runnable for me? Specifically, both front-end and back-end part contain some issues. The front-end part complains about Angular version of some packages, the thing is we are using Angular 19 in our projects, but this test project has been generated for the latest version and therefore uses Angular 20. All in all, this test solution - while not helping us to identify this specific error root cause - still may come in handy for other tests in the future.

As for the error in question - there should be the explanation why specifically ABP application configuration serice invocation (a standard implementation) from a client causes this error. Do you have any ideas to check?

Thank you.

P.S. We still use a traditional app.module.ts / app-routing.module.ts approach in our solution after migration. Could it be the reason of this 'extra-invocation' of ABP application configuration service? In our front-end code, we do not explicitly invoke AbpApplicationConfigurationService.

I've noticed other duplicated calls:

You were right about it: I have removed this custom code and the error is still there, with a default ABP application configuration service. So - please update my test ABP project in the shared link to make it runnable, so we may proceed troubleshooting this issue. Thanks.

BTW, I have the idea why there could be a timeout. We have a custom configuration which adds so-called module permissions to the output. Please have a look, maybe you have the idea how to improve this. But one way or another, we need to get this information on client-side. I thought about using caching here in a more efficient way. But I'd prefer the permission information remained up-to-date and besides, it won't eliminate the cancellation during the first call (unless we warm-up the configuration data somehow in advance):

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(IAbpApplicationConfigurationAppService))]
    public class ModulePermissionApplicationConfigurationAppService : AbpApplicationConfigurationAppService, IAbpApplicationConfigurationAppService
    {
        private readonly IPermissionGrantRepository _permissionGrantRepository;
        private readonly IModulePermissionChecker _modulePermissionChecker;
    
        public ModulePermissionApplicationConfigurationAppService
        (
            IPermissionGrantRepository permissionGrantRepository,
            IModulePermissionChecker modulePermissionChecker,
            IOptions<AbpLocalizationOptions> localizationOptions,
            IOptions<AbpMultiTenancyOptions> multiTenancyOptions,
            IServiceProvider serviceProvider,
            IAbpAuthorizationPolicyProvider abpAuthorizationPolicyProvider,
            IPermissionDefinitionManager permissionDefinitionManager,
            DefaultAuthorizationPolicyProvider defaultAuthorizationPolicyProvider,
            IPermissionChecker permissionChecker,
            IAuthorizationService authorizationService,
            ICurrentUser currentUser,
            ISettingProvider settingProvider,
            ISettingDefinitionManager settingDefinitionManager,
            IFeatureDefinitionManager featureDefinitionManager,
            ILanguageProvider languageProvider,
            ITimezoneProvider timezoneProvider,
            IOptions<AbpClockOptions> abpClockOptions,
            ICachedObjectExtensionsDtoService cachedObjectExtensionsDtoService,
            IOptions<AbpApplicationConfigurationOptions> options
        ) : base
            (
                localizationOptions,
                multiTenancyOptions,
                serviceProvider,
                abpAuthorizationPolicyProvider,
                permissionDefinitionManager,
                defaultAuthorizationPolicyProvider,
                permissionChecker,
                authorizationService,
                currentUser,
                settingProvider,
                settingDefinitionManager,
                featureDefinitionManager,
                languageProvider,
                timezoneProvider,
                abpClockOptions,
                cachedObjectExtensionsDtoService,
                options
            )
        {
            _permissionGrantRepository = permissionGrantRepository;
            _modulePermissionChecker = modulePermissionChecker;
        }
    
        public override async Task<ApplicationConfigurationDto> GetAsync(ApplicationConfigurationRequestOptions options)
        {
            var result = await base.GetAsync(options);
    
            var moduleRoleNames = await _modulePermissionChecker.GetModuleRoleNamesAsync();
    
            Dictionary<string, HashSet<string>> modulePermissionMap;
    
            using (CurrentTenant.Change(null))
            {
                var moduleRolePermissionGrants = await _permissionGrantRepository.GetListAsync();
    
                modulePermissionMap = moduleRoleNames
                    .GroupJoin
                    (
                        moduleRolePermissionGrants.Where(pg => pg.ProviderName == RolePermissionValueProvider.ProviderName),
                        moduleRoleName => moduleRoleName,
                        permissionGrant => permissionGrant.ProviderKey,
                        (moduleRoleName, permissionGrants) => (moduleRoleName, permissionGrantNames: permissionGrants.Select(x => x.Name))
                    )
                    .GroupBy(x => x.moduleRoleName.GetModuleId())
                    .Where(group => group.Key != null)
                    .ToDictionary(x => x.Key, x => x.SelectMany(moduleRolePermission => moduleRolePermission.permissionGrantNames).ToHashSet());
            }
    
            var ordinaryRolePermissionGrants = await _permissionGrantRepository.GetListAsync();
    
            modulePermissionMap.Add
            (
                "_ordinaryRole",
                CurrentUser.Roles
                    .GroupJoin
                    (
                        ordinaryRolePermissionGrants.Where(pg => pg.ProviderName == RolePermissionValueProvider.ProviderName),
                        ordinaryRoleName => ordinaryRoleName,
                        permissionGrant => permissionGrant.ProviderKey,
                        (ordinaryRoleName, permissionGrants) => (ordinaryRoleName, permissionGrantNames: permissionGrants.Select(x => x.Name))
                    )
                    .SelectMany(x => x.permissionGrantNames).ToHashSet()
            );
    
            result.ExtraProperties.Add("modulePermissionMap", modulePermissionMap);
    
            return result;
        }
    }
    
    public class ModulePermissionChecker : IModulePermissionChecker
    {
        private readonly IDistributedCache<ModulePermissionCacheItem> _modulePermissionCache;
        private readonly IDistributedCache<AbpPermissionCacheItem> _abpPermissionCache;
        private readonly IIdentityUserRepository _identityUserRepository;
        private readonly IPermissionGrantRepository _permissionGrantRepository;
        private readonly IPermissionDefinitionRecordRepository _permissionDefinitionRecordRepository;
        private readonly ICurrentTenant _currentTenant;
        private readonly ICurrentUser _currentUser;
        private readonly int CacheExpirationDay = 1;
        private string ModulePermissionCacheKey => $"ModulePermission:{_currentUser.Id}";
        private string AbpPermissionCacheKey => $"AbpPermission:{_currentUser.Id}";
    
        public ModulePermissionChecker
        (
            IIdentityUserRepository identityUserRepository,
            IPermissionGrantRepository permissionGrantRepository,
            IPermissionDefinitionRecordRepository permissionDefinitionRecordRepository,
            IDistributedCache<ModulePermissionCacheItem> modulePermissionCache,
            IDistributedCache<AbpPermissionCacheItem> abpPermissionCache,
            ICurrentTenant currentTenant,
            ICurrentUser currentUser
        )
        {
            _identityUserRepository = identityUserRepository;
            _permissionGrantRepository = permissionGrantRepository;
            _permissionDefinitionRecordRepository = permissionDefinitionRecordRepository;
            _modulePermissionCache = modulePermissionCache;
            _abpPermissionCache = abpPermissionCache;
            _currentTenant = currentTenant;
            _currentUser = currentUser;
        }
    
        public async Task<HashSet<string>> GetModuleRoleNamesAsync()
        {
            if (!_currentUser.IsAuthenticated)
            {
                return new HashSet<string>();
            }
            var modulePermissionCacheItem = await _modulePermissionCache.GetOrAddAsync
            (
                ModulePermissionCacheKey,
                GetModulePermissionCacheItemAsync,
                () => new DistributedCacheEntryOptions
                {
                    AbsoluteExpiration = DateTimeOffset.Now.AddDays(CacheExpirationDay)
                }
            );
    
            return modulePermissionCacheItem.ModuleRoleNames;
        }
    
        public async Task<HashSet<string>> GetAbpPermissionsAsync()
        {
            if (!_currentUser.IsAuthenticated)
            {
                return new HashSet<string>();
            }
            var abpPermissionCacheItem = await _abpPermissionCache.GetOrAddAsync
            (
                AbpPermissionCacheKey,
                GetAbpPermissionCacheItemAsync,
                () => new DistributedCacheEntryOptions
                {
                    AbsoluteExpiration = DateTimeOffset.Now.AddDays(CacheExpirationDay)
                }
            );
    
            return abpPermissionCacheItem.Permissions;
        }
    
        private async Task<ModulePermissionCacheItem> GetModulePermissionCacheItemAsync()
        {
            var ordinaryRoleNames = await _identityUserRepository.GetRoleNamesAsync(_currentUser.Id.Value);
            var moduleRoleNames = new HashSet<string>();
    
            foreach (var ordinaryRoleName in ordinaryRoleNames)
            {
                var permissionGrantsAkaModuleRoles = await _permissionGrantRepository.GetListAsync(ModulePermissionConsts.RoleProviderName, ordinaryRoleName);
                permissionGrantsAkaModuleRoles.ForEach(permissionGrantAkaModuleRole =>
                {
                    moduleRoleNames.Add(permissionGrantAkaModuleRole.Name);
                });
            };
    
            return new ModulePermissionCacheItem { ModuleRoleNames = moduleRoleNames };
        }
    
        private async Task<AbpPermissionCacheItem> GetAbpPermissionCacheItemAsync()
        {
            var permissions = new HashSet<string>();
    
            var abpPermissionDefinitions = (await _permissionDefinitionRecordRepository.GetListAsync()).Where(pd => ModulePermissionConsts.AbpRelatedPermissionGroups.Contains(pd.GroupName));
    
            return new AbpPermissionCacheItem { Permissions = abpPermissionDefinitions.Select(x => x.Name).ToHashSet() };
        }
    }
Showing 1 to 10 of 345 entries
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.1.0-preview. Updated on October 30, 2025, 06:33