Activities of "maliming"

: )

Answer

Great

Hi,

Sounds good. Once you've had a chance to try it, let us know how it goes. If anything doesn't work as expected, share whatever details you can — timings, a small repro, or send the code via email if that's easier — and we'll keep digging on our side.

Thanks

Hi,

Could you share _installer.InstallAsync? We'd like to see exactly how the rows are being written — IRepository<T>.InsertAsync in a loop, InsertManyAsync, _dbContext.AddRange + SaveChangesAsync, or something else.

One thing to flag up front — [DisableEntityChangeTracking] and repository.DisableTracking() only affect read queries, not InsertAsync / UpdateAsync. The docs are explicit about this:

Change tracking behavior doesn't affect tracking entity objects returned from InsertAsync and UpdateAsync methods.

So those attributes won't change anything on the insert path.

Here's an approach you can try — a small replacement for IEntityChangeEventHelper that suppresses entity events for an explicit using scope. Could you drop this into your project, wrap the import call site like below, and let us know whether CompleteAsync drops to something reasonable on your 1M case?

[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IEntityChangeEventHelper), typeof(EntityChangeEventHelper))]
public class ScopedEntityChangeEventHelper : EntityChangeEventHelper
{
    private static readonly AsyncLocal<bool> _suppressed = new();

    public ScopedEntityChangeEventHelper(
        IUnitOfWorkManager uowManager,
        IEntityToEtoMapper etoMapper,
        IOptions<AbpDistributedEntityEventOptions> options)
        : base(uowManager, etoMapper, options) { }

    public static IDisposable Suppress()
    {
        var prev = _suppressed.Value;
        _suppressed.Value = true;
        return new DisposeAction(() => _suppressed.Value = prev);
    }

    public override void PublishEntityCreatedEvent(object entity)
    {
        if (!_suppressed.Value) base.PublishEntityCreatedEvent(entity);
    }

    public override void PublishEntityUpdatedEvent(object entity)
    {
        if (!_suppressed.Value) base.PublishEntityUpdatedEvent(entity);
    }

    public override void PublishEntityDeletedEvent(object entity)
    {
        if (!_suppressed.Value) base.PublishEntityDeletedEvent(entity);
    }
}

Usage at your import call site — _installer.InstallAsync itself stays unchanged:

using var _ = ScopedEntityChangeEventHelper.Suppress();
using var uow = _unitOfWorkManager.Begin(requiresNew: true, isTransactional: false);
await _installer.InstallAsync(data);
await uow.CompleteAsync();

The effect is scoped to the using block, so the rest of your app keeps behaving normally.

To be clear about what this does and doesn't touch — it only intercepts the per-entity broadcast events (EntityCreatedEventData<T> / EntityUpdatedEventData<T> / EntityDeletedEventData<T> and their distributed Eto counterparts). Everything else ABP normally does for tracked entities keeps running: CreationTime / CreatorId / LastModificationTime / ConcurrencyStamp are still set automatically, multi-tenancy and soft-delete still work, and any domain events you raise yourself with entity.AddLocalEvent(...) / AddDistributedEvent(...) go through a different pipeline and are not affected.

If you do have any local or distributed event handlers subscribed to EntityCreatedEventData<T> / EntityCreatedEto<T> for the entities being inserted, those will be skipped during the import — usually fine for a bulk install, but worth confirming on your side.

Thanks

Answer

Hi Stefano,

Glad to hear SaveTokens = false brought the app back. That's actually the right fix here — let me explain why so the picture is complete.

I was looking at the wrong cookie in my previous reply. The 8.8KB you saw is the External cookie (.AspNetCore.Identity.External, often chunked into Identity.ExternalC1 / C2), not the Application cookie. That External cookie is short-lived — it's created when Okta's callback hits /signin-okta, lives just long enough to ride one redirect to /Account/Login?handler=ExternalLoginCallback, and then ABP signs it out as part of the external login flow. But that one redirect is the request where Azure App Service's header limit gets hit, which is where the 502 came from.

SaveTokens = true takes Okta's id_token and access_token and stores them inside that External cookie's AuthenticationProperties. Okta's tokens can each be a few KB on their own (especially when the access_token or id_token carries a lot of claims — groups, profile attributes, app-specific scopes, etc.). Once the cookie gets serialized, encrypted, and chunked, it lands in the 6-9KB range, which lines up with what you saw. Setting SaveTokens = false strips the tokens out and the cookie drops to a few hundred bytes.

So please ignore my previous questions about role counts and custom claims — that line of investigation doesn't apply to your case. Sorry for the noise.

A couple of things to keep in mind going forward:

  1. As long as your server-side code doesn't need to call Okta APIs (/userinfo, Okta Management API, etc.) on behalf of the user, SaveTokens = false is a clean permanent fix. From your CalendarWebModule it doesn't look like you're using the tokens on the server, so you're good.

  2. If you ever do need server-side access to Okta tokens later, two options:

    • Trim what Okta puts in the tokens — reduce the claims/groups returned in id_token / access_token from the Okta authorization server configuration. Often you can cut a lot just by not embedding the full groups list, or by moving large attributes out of the token.
    • Move tokens out of the cookie into a server-side store — keep SaveTokens = false, then in the Okta scheme use options.Events.OnTokenValidated to copy the tokens into IDistributedCache (Redis on Azure for multi-instance setups) keyed by user, and read them from there in your code. Keeps the cookie small while still giving you tokens on the server.

Thanks

Hi,

The default abp login uses the OIDC authorization code flow, which tries to open a browser on the local machine. On a headless Linux server there is no browser to open, so gio open / xdg-open fail.

Use the device code flow instead:

abp login --device

You will see something like:

[INF] Open your browser, go to: "https://account.abp.io/connect/verify"
[INF] and enter the following one-time code:
[INF] 4071-9666-6235

Open the URL on any device with a browser (e.g. your laptop), enter the code, sign in, and the CLI on the Linux box will pick up the login automatically.

Thanks

Hi,

Pass --skip-extension-version-check (or -sevc) to abp install-libs. install-libs doesn't use the Studio extensions at all, so the auto-update/respawn path can be safely skipped and the step will run synchronously without the second run or the continueOnError trick.

We'll also add install-libs to the auto-skip list in the next CLI release, so the flag won't be needed.

Thanks

Answer

Hi,

Let me start with what's actually in that 8.8KB cookie so we can narrow down where it's coming from.

The Okta tokens and claims don't end up in the application cookie at all. ABP's external login callback signs out the External cookie right after ExternalLoginSignInAsync succeeds, and then SignInManager.SignInAsync(user, false) creates a fresh Application cookie from the local user record only. So SaveTokens = true on the Okta scheme isn't what's growing it, and neither is anything else in the OIDC config.

What goes into the Application cookie on sign-in is:

  • Standard local user fields (id, username, email, phone, security stamp, tenant id, etc.) — around 300 bytes in a fresh ABP project
  • One role claim for every role the user is in
  • Everything stored in AbpUserClaims for that user
  • Everything stored in AbpRoleClaims for every role that user has

Dynamic claims (UseDynamicClaims() and IsDynamicClaimsEnabled = true) only enrich the principal per request — they never write to the cookie, so that feature isn't growing it either.

The first item is roughly the same in any ABP project. The other three are where 8KB+ typically comes from. To narrow it down, could you tell us:

  1. Roughly how many roles is this user assigned to?
  2. Has anyone added custom claims to users or roles — either through the Identity admin UI (User / Role → Claims tab) or by code that writes to AbpUserClaims / AbpRoleClaims?
  3. If yes to the second one, are any of those claims synced from Okta (for example, Okta groups copied over as local claims)?

Once we have those answers we can pick the right next step.

Thanks

Hi,

To narrow this down, could you share a few things:

  1. Your MyApplication.Domain.Shared.csproj (full file).
  2. Your MyApplicationDomainSharedModule.cs — specifically the ConfigureServices method.
  3. The full JSON response from /api/abp/application-localization?cultureName=en — we'd like to see whether other resources (like AbpIdentity, AbpUi, etc.) also have empty texts, or only your MyApplication resource.

In the meantime, you can try this. Your symptom usually comes from Microsoft.Extensions.FileProviders.Embedded being missing or pruned in Domain.Shared after upgrading across .NET versions. Without that package, the manifest XML isn't embedded into your Domain.Shared.dll, ABP's virtual file system can't find your en.json, and the endpoint returns texts: {} while the resource itself is still registered (which matches what you're seeing — the resource shows up with the correct baseResources, just no texts).

Make sure MyApplication.Domain.Shared.csproj has all three pieces below:

<PropertyGroup>
  <GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
</PropertyGroup>

<ItemGroup>
  <EmbeddedResource Include="Localization\MyApplication\*.json" />
  <Content Remove="Localization\MyApplication\*.json" />
</ItemGroup>

<ItemGroup>
  <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.7" />
</ItemGroup>

Then run dotnet clean && dotnet build and restart the host. The MyApplication resource should start returning its texts.

If all three pieces are already in place, send over the csproj and module file and we'll dig deeper.

Thanks

Hi,

The reorder is a default sort behavior change in the framework, not something you did. In v8.x the nav items service sorted strictly by order, so when several items share the same order (the three default items all use 100), Array.sort preserved their insertion order: languages | current-user | full-screen. From v10 the menu service routes through a shared sort function that breaks ties by id alphabetically, and the ids happen to be Theme.CurrentUserComponent < Theme.FullScreenComponent < Theme.LanguagesComponent, so you end up with the new order.

To restore the previous order without replacing any component, patch the three items via NavItemsService.patchItem:

import { Component, inject } from &#39;@angular/core&#39;;
import { NavItemsService } from &#39;@abp/ng.theme.shared&#39;;
import { eThemeLeptonComponents } from &#39;@volo/abp.ng.theme.lepton&#39;;

@Component({
  selector: &#39;app-root&#39;,
  template: &#39;&lt;router-outlet /&gt;',
})
export class AppComponent {
  private navItems = inject(NavItemsService);

  constructor() {
    this.navItems.patchItem(eThemeLeptonComponents.Languages, { order: 1 });
    this.navItems.patchItem(eThemeLeptonComponents.CurrentUser, { order: 2 });
    this.navItems.patchItem(eThemeLeptonComponents.FullScreen, { order: 3 });
  }
}

The AppComponent constructor is the easiest place — it runs after the theme registers its default items, so the patches always find them.

About FontAwesome 5: we don't recommend pinning @abp/ng.theme.shared or @volo/abp.ng.theme.lepton to older versions to keep FA5, because the theme packages are designed to match the framework version and downgrading them breaks compatibility with other ABP Angular packages on 10.4. If you really want the FA5 look, the only safe option is to import FA5 stylesheet into your own styles.scss and override the icon classes used in the affected components with CSS — it's doable but maintenance-heavy and we don't actively support it.

Thanks

Showing 341 to 350 of 12914 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.8.0-preview. Updated on November 02, 2026, 06:56
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.