Activities of "AI-Bot"

  • In ABP Blazor (including Blazor Web App) the Identity Users page is a server-side paged list. The order is determined by the Sorting field sent in the GetListAsync request (a PagedAndSortedResultRequestDto / GetIdentityUsersInput-like DTO).
  • To sort the list, set a default sorting value (and/or make the grid send the current sorting) by overriding the Identity UserManagement page/component and assigning GetListInput.Sorting.

Option A) Set a default sort (e.g., by UserName)

  1. Create a new page/component that replaces the built-in one (same technique used for overriding built-in Identity pages):
@* YourProject.Blazor/Pages/Identity/UserManagement.razor *@
@using Volo.Abp.Identity.Blazor.Pages.Identity
@using Volo.Abp.DependencyInjection

@attribute [ExposeServices(typeof(UserManagement))]
@attribute [Dependency(ReplaceServices = true)]

@inherits UserManagement
  1. In the code-behind, set Sorting before loading:
// YourProject.Blazor/Pages/Identity/UserManagement.razor.cs
using System.Threading.Tasks;

namespace YourProject.Blazor.Pages.Identity;

public partial class UserManagement
{
    protected override async Task UpdateGetListInputAsync()
    {
        await base.UpdateGetListInputAsync();

        if (string.IsNullOrWhiteSpace(GetListInput.Sorting))
        {
            // Pick any valid field exposed by the backend DTO:
            // e.g. "UserName", "Name", "Email", etc.
            GetListInput.Sorting = "UserName asc";
        }
    }
}

Now the page will always request users sorted by UserName asc unless the UI sets another sorting.

Option B) Sort based on the grid’s current sorting

If you want clicking column headers to sort, ensure the page sets:

GetListInput.Sorting = CurrentSorting;

(where CurrentSorting is the value produced by the ABP CRUD/grid base page logic). This is the same pattern used in ABP Blazor CRUD pages to pass sorting to the backend.


(light) references

  • https://abp.io/docs/latest/UI/Blazor/Customization-Overriding-Components
  • https://abp.io/support/questions/5811

This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • Since your mobile app is using the system browser/custom tab, the 400 on "/Account/Login" with missing ".AspNetCore.Antiforgery.*" cookie is almost always a cookie not being stored/sent back during the login POST inside that browser session.
  • The iOS-vs-Android difference strongly points to a SameSite/Secure cookie policy / HTTP-vs-HTTPS behavior difference (Android Chrome / Custom Tabs tend to be stricter/behave differently than iOS Safari/WebKit in some setups). When the antiforgery cookie is not persisted/sent, the POST to /Account/Login fails exactly like your log.

Solution

  1. Ensure you are using HTTPS end-to-end for the Authority
  • Make sure the AuthServer:Authority you use in the mobile OIDC config is https://... (not http://...) and the browser is actually hitting HTTPS.
  • If you are testing behind a proxy / ingress, ensure forwarded headers are configured so ASP.NET Core knows the original scheme is HTTPS; otherwise cookies can be emitted without Secure and then dropped/not returned by modern browsers.
  1. Apply a SameSite cookie policy workaround (ABP’s documented approach) Add a SameSite cookie policy to deal with browser incompatibilities, then enable UseCookiePolicy() early.

In your *.Web (or the host project that serves the /Account/* pages), add:

ConfigureServices

context.Services.AddSameSiteCookiePolicy();

OnApplicationInitialization (before auth middleware that writes cookies)

app.UseCookiePolicy();

This is the approach used to fix browser-specific login cookie issues.

  1. Do not try to disable antiforgery for this Your symptom is not “ABP antiforgery is incorrectly enabled for a non-browser client”; it’s “the browser did not return the antiforgery cookie”. Disabling antiforgery just masks the underlying cookie issue and weakens the login endpoint.

Links (validated)

  • https://abp.io/community/articles/patch-for-chrome-login-issue-identityserver4-samesite-cookie-problem-weypwp3n
  • https://learn.microsoft.com/en-us/aspnet/core/security/samesite?view=aspnetcore-9.0
  • https://abp.io/docs/latest/framework/infrastructure/csrf-anti-forgery
  • https://abp.io/support/questions/9426

This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • Your setting Configure<AbpAntiForgeryOptions>(o => o.AutoValidate = false) disables ABP’s global [AbpAutoValidateAntiforgeryToken] behavior for MVC/API endpoints, but your error is coming from Microsoft’s built-in Razor Pages antiforgery filter: Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.AutoValidateAntiforgeryTokenAuthorizationFilter and the failing endpoint is the Razor Page /Account/Login.

  • In ABP (with the Account module), /Account/Login is a Razor Page and it’s expected to be protected by antiforgery because it is a cookie-based, browser login page. For mobile OIDC (Authorization Code + PKCE), you typically should not POST to /Account/Login from the mobile app at all. The mobile app should start the OIDC authorize flow in a system browser/custom tab, and the browser will handle cookies + antiforgery correctly.

  • If you still want to allow posting to /Account/Login without antiforgery (not recommended), do it specifically for that Razor Page by overriding the login page model and suppressing antiforgery validation.

Solution

  1. Keep ABP antiforgery enabled (recommended) and don’t call /Account/Login from the mobile app
  • For Flutter/Maui AppAuth you should use:
    • /connect/authorize (system browser)
    • /connect/token (back-channel)
  • Do not automate a form POST to /Account/Login from the app. That endpoint is designed for interactive browser login.
  1. If you must disable antiforgery for /Account/Login, override the Razor Page and ignore antiforgery
  • In your *.HttpApi.Host (or *.Web) project, create:

Pages/Account/Login.cshtml.cs

using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Account.Web.Pages.Account;

namespace MyCompany.MyApp.HttpApi.Host.Pages.Account;

[IgnoreAntiforgeryToken] // disables Razor Pages antiforgery validation for this page
public class LoginModel : Volo.Abp.Account.Web.Pages.Account.LoginModel
{
    public LoginModel(
        Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider schemeProvider,
        Microsoft.Extensions.Options.IOptions<Volo.Abp.Account.Web.AbpAccountOptions> accountOptions,
        Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Identity.IdentityOptions> identityOptions,
        Volo.Abp.Identity.IdentityDynamicClaimsPrincipalContributorCache contributorCache)
        : base(schemeProvider, accountOptions, identityOptions, contributorCache)
    {
    }
}

Pages/Account/Login.cshtml

  • Create Pages/Account/Login.cshtml to override the UI (you can copy the original ABP login page markup from the Account module as described in ABP’s “customize login page” approach). The key part for antiforgery is the Login.cshtml.cs with [IgnoreAntiforgeryToken].
  1. Remove your attempt to remove AutoValidateAntiforgeryTokenAttribute from MvcOptions
  • That code targets MVC filters/attributes and won’t reliably remove the Razor Pages antiforgery filter that’s actually rejecting /Account/Login.

Notes (important for your symptom)

  • ABP’s antiforgery system already bypasses validation for non-browser clients, but your failing request is to a Razor Page login endpoint, which is a browser/cookie flow and therefore expects antiforgery.
  • If your mobile HTTP client is carrying cookies (or behaving like a browser), you can also trigger antiforgery expectations in some flows. But again: mobile should not be posting to /Account/Login in the first place for OIDC.

Sources

  • https://abp.io/docs/latest/framework/infrastructure/csrf-anti-forgery
  • https://abp.io/support/questions/3338
  • https://abp.io/support/questions/1895

This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • In ABP MVC, the “Back to my account” button is shown only if the current principal contains the impersonation claim (i.e., ICurrentUser.FindImpersonatorUserId() != null). So the fastest way to debug is to verify whether impersonation is still active (claims/cookies) and whether the toolbar item is still being contributed.

1) Verify impersonation is actually active (claim exists)

  1. While impersonating, open your page and inspect the authenticated user’s claims (e.g., put a breakpoint / temporary log in any MVC action):
    • Check CurrentUser.FindImpersonatorUserId() is NOT null.
  2. If it’s null, the “back” button will not render. In that case, impersonation may still “look like it worked” (you’re logged in as the user) but the impersonator info wasn’t persisted (usually due to cookies/auth pipeline changes, custom account controller, reverse proxy cookie issues, etc.).

2) Ensure the UI part (toolbar contribution) exists in your app

For MVC, the button is not “magic”; it comes from the impersonation UI integration. If you customized your toolbar/layout/theme, you may have removed the contributor/view component that renders it.

Make sure you followed the MVC impersonation UI setup:

  • Your Web module depends on the impersonation web module.
  • Your toolbar includes an item (often via a toolbar contributor) that conditionally adds the button when FindImpersonatorUserId() != null.
  • The endpoint POST ~/Account/BackToImpersonator exists (it’s the action the button posts to).

If you’ve overridden AccountController, confirm it still inherits from the impersonation-enabled base controller as required by the docs.

3) Quick isolation test: add the button manually

To prove it’s only a UI/toolbar problem (not claims), temporarily add this to your main layout (or a toolbar area) and test while impersonating:

@using Volo.Abp.Account.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@inject IHtmlLocalizer<AccountResource> L

<form method="post" data-ajaxForm="false" action="~/Account/BackToImpersonator">
    @Html.AntiForgeryToken()
    <button type="submit" class="btn btn-link text-danger">
        @L["BackToImpersonator"]
    </button>
</form>
  • If this appears and works, your problem is toolbar contributor / theme component not being executed or not rendering.
  • If it posts but fails, then it’s not a rendering problem; check the action route and auth cookies/claims.

4) Common real cause: theme/mobile toolbar placement

There is a known case where the button is not visible depending on responsive/mobile toolbar placement (especially with LeptonX). In older versions it was fixed by upgrading (example reported/fixed in later versions for mobile view). Even on desktop, if your theme moved the user menu into a different place, the button may now be under the username menu instead of the top bar.

5) Confirm you didn’t restrict the toolbar contributor to a different toolbar

If you have custom IToolbarContributor code, ensure it’s contributing to the toolbar your layout uses (e.g., StandardToolbars.Main). A wrong toolbar name check can prevent the item from being added.


Links I verified:

  • https://abp.io/docs/latest/modules/account/impersonation
  • https://abp.io/support/questions/6212

This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • Your external provider flow is actually succeeding and ABP is posting to /Account/Register?isExternalLogin=True to auto-create/link the user.
  • The HTTP 400 you see is caused by ABP’s antiforgery validation on the error page pipeline, with this key log line:
    The provided antiforgery token was meant for a different claims-based user than the current user.
  • In your log, the real breaking exception is not ABP but your custom code running right after the user is created:
    System.Collections.Generic.KeyNotFoundException: The given key 'IsSeeding' was not present in the dictionary.
    in Cns.Cloud.Apps.Users.UserCreatedEventHandler.HandleEventAsync(...).

So you have two issues:

  1. Your UserCreatedEventHandler throws, which breaks the request (this is the primary failure).
  2. The antiforgery warning/400 is a side-effect of the pipeline ending up on /Error?httpStatusCode=400 with a changed user context.

Fix (definitive)

  1. Fix your event handler to not assume IsSeeding exists (use TryGetValue / ContainsKey, or provide a default). Example pattern:
public Task HandleEventAsync(EntityCreatedEto<IdentityUserEto> eventData)
{
    // Example: if you stored extra properties somewhere, never index directly
    // var isSeeding = dict["IsSeeding"]; // <- unsafe

    var isSeeding = false;
    if (eventData.Properties != null &&
        eventData.Properties.TryGetValue("IsSeeding", out var value) &&
        value is bool b)
    {
        isSeeding = b;
    }

    if (isSeeding)
    {
        return Task.CompletedTask;
    }

    // normal logic...
    return Task.CompletedTask;
}

(Adapt to your actual dictionary/object; the key point is don’t index with [...] unless you’re 100% sure it’s there.)

  1. After fixing that exception, the external-login-first-time flow should complete without redirecting into an error path, and the antiforgery 400 should disappear.

Notes (what ABP is doing)

  • ABP’s Account module can register external users on first login (that’s why /Account/Register?isExternalLogin=True appears).
  • If you are using OpenIdConnect/AzureAD, make sure your provider configuration includes correct claim mappings/scopes (especially email) as described in the ABP article below.

Sources

  • https://abp.io/community/articles/4603b9cf
  • https://abp.io/support/questions/10356

This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • ABP’s built-in Emailing settings UI (Setting Management → Emailing) is designed for SMTP settings. There is no native tenant-level OAuth2 UI for the email sender in ABP 10.0.
  • The recommended/working approach is to make email sending tenant-aware by:
    1. Storing OAuth configuration per tenant (via Setting Management or your own entity),
    2. Replacing IEmailSender with your own implementation that reads the current tenant’s configuration and sends using OAuth (e.g., Microsoft Graph, Gmail API, or SMTP with OAuth2 via MailKit if that’s your provider).

1) Store per-tenant OAuth settings (Setting Management)

Define your own setting names and register them with a SettingDefinitionProvider. ABP settings are automatically resolved per-tenant.

public static class TenantEmailOAuthSettings
{
    private const string Prefix = "MyApp.Email.OAuth";

    public const string Provider = Prefix + ".Provider";           // e.g. "MicrosoftGraph", "Gmail"
    public const string TenantId = Prefix + ".TenantId";
    public const string ClientId = Prefix + ".ClientId";
    public const string ClientSecret = Prefix + ".ClientSecret";
    public const string FromAddress = Prefix + ".FromAddress";
    public const string FromDisplayName = Prefix + ".FromDisplayName";
}

Then, create a custom settings UI page (Blazor Server) similar to how custom setting pages are added (same technique as “white labeling” examples: define settings + implement an app service using ISettingManager + add a UI page/group).

2) Replace IEmailSender with a tenant-aware OAuth sender

Implement IEmailSender and read settings using ISettingProvider (which resolves values in the context of the current tenant).

using System.Net.Mail;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Emailing;
using Volo.Abp.Settings;

public class TenantOAuthEmailSender : IEmailSender, ITransientDependency
{
    private readonly ISettingProvider _settingProvider;

    public TenantOAuthEmailSender(ISettingProvider settingProvider)
    {
        _settingProvider = settingProvider;
    }

    public async Task SendAsync(MailMessage mail, bool normalize = true)
    {
        // Read per-tenant OAuth configuration
        var provider = await _settingProvider.GetOrNullAsync(TenantEmailOAuthSettings.Provider);
        var clientId = await _settingProvider.GetOrNullAsync(TenantEmailOAuthSettings.ClientId);
        var clientSecret = await _settingProvider.GetOrNullAsync(TenantEmailOAuthSettings.ClientSecret);

        // Use these to send via your chosen OAuth provider (Graph/Gmail/etc.)
        // (Implementation depends on provider; this is where you call Graph API, etc.)
        throw new NotImplementedException();
    }

    public Task SendAsync(string to, string subject, string body, bool isBodyHtml = true)
        => SendAsync(new MailMessage { Subject = subject, Body = body, IsBodyHtml = isBodyHtml, To = { to } });

    public Task SendAsync(string from, string to, string subject, string body, bool isBodyHtml = true)
        => SendAsync(new MailMessage(from, to, subject, body) { IsBodyHtml = isBodyHtml });

    public Task QueueAsync(string to, string subject, string body, bool isBodyHtml = true)
        => SendAsync(to, subject, body, isBodyHtml); // or integrate with background jobs
}

Register it by replacing ABP’s default email sender:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.Modularity;

public class MyAppEmailModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.Replace(ServiceDescriptor.Transient<IEmailSender, TenantOAuthEmailSender>());
    }
}

3) Make the settings editable by tenants (ABP UI / SaaS)

If you want tenants to edit email-related settings themselves, ABP can gate this via tenant features (SaaS). In practice, you enable the relevant tenant feature in the SaaS tenant management screen (this is how built-in “Emailing” settings visibility is controlled).

4) If you need “OAuth + SMTP” specifically

ABP’s default UI won’t cover OAuth flows. You typically:

  • Create your own page to capture client id/secret/tenant id and perform admin consent / token acquisition (provider-specific),
  • Persist the resulting tokens/credentials per tenant,
  • Use them in your IEmailSender implementation.

Sources (verified)

  • https://abp.io/docs/latest/framework/infrastructure/emailing
  • https://abp.io/support/questions/10065
  • https://abp.io/support/questions/7579

This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • changePasswordToken is not an OpenIddict/OpenID Connect token type and there is no built-in OAuth/OIDC endpoint (like /connect/token) that “uses” it in ABP.

  • In ABP, a “change password / reset password token” is an ASP.NET Core Identity user token (generated by UserManager.GeneratePasswordResetTokenAsync(...) / related APIs) and it must be consumed by an ABP Account endpoint (HTTP API) that performs the password change/reset (not the OpenIddict token endpoint).

  • So the correct flow is typically:

    1. Call an account endpoint to initiate the reset/forgot-password flow (server generates token + sends email/link, or returns token depending on your customization).
    2. Call an account endpoint to submit the token + new password (server verifies the token via Identity and changes the password).
    3. After password is changed, obtain an access token normally via OpenIddict (/connect/token with password / authorization_code / etc.).
  • If your goal is: “I want to exchange changePasswordToken for an access token at /connect/token”, that’s not supported by default. You would need to implement a custom OpenIddict extension grant (ITokenExtensionGrant) and validate your token yourself, then issue an access token.

    Minimal outline (ABP’s OpenIddict extension grant mechanism):

    • Register your custom grant name in OpenIddictServerOptions.GrantTypes
    • Register an ITokenExtensionGrant implementation in AbpOpenIddictExtensionGrantsOptions
    • In HandleAsync(...), validate the incoming token and return SignInResult to generate a token response.

Sources (validated):

  • https://abp.io/community/articles/6v0df94z
  • https://github.com/abpframework/abp/blob/dev/modules/openiddict/app/OpenIddict.Demo.Server/ExtensionGrants/MyTokenExtensionGrant.cs

This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

Please contact us at https://abp.io/contact.


This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • Yes, AutoMapper and Mapperly can coexist in the same ABP 10+ solution. ABP 10 switched ABP modules/templates to use Mapperly by default, but ABP still provides both AutoMapper and Mapperly integration packages, so you can keep existing AutoMapper profiles while using Mapperly elsewhere (or for ABP-provided modules).

  • What “coexistence” practically means in ABP

    • ABP’s mapping abstraction is IObjectMapper / ObjectMapper.Map(...).
    • Under the hood, ABP uses an “auto object mapping provider” (Mapperly or AutoMapper integration) to resolve mappings.
    • You can register Mapperly as the default provider for the application, while still keeping AutoMapper available via module/context-based object mappers (or vice-versa). This enables a phased transition.
  • Recommended best practices / common pitfalls when using both

    1. Be explicit about mapping context when you register a module-specific mapper
      • If you register an object mapper with a context (generic registration), consumers must use the same context.
      • Example pattern (contextual mapper usage):
        • Register in a module:
context.Services.AddAutoMapperObjectMapper<MyBlazorModule>();
         // or
         context.Services.AddMapperlyObjectMapper<MyBlazorModule>();
   - Then set the context where you map (e.g., in an `ApplicationService` / Blazor page base):
ObjectMapperContext = typeof(MyBlazorModule);
 - Otherwise, ABP may fall back to the *default* provider and you can get “no mapping found” errors (especially visible in UI layers like Blazor).
  1. Avoid ambiguous/duplicate mappings for the same source/destination pair

    • If you define the same mapping pair in both libraries, it becomes unclear which one should be used (depending on which provider/context is active). Prefer a clear rule: “old mappings stay in AutoMapper until migrated” and “new mappings go to Mapperly”.
  2. Decide which one is the default provider for ObjectMapper.Map

    • If you want ABP’s default ObjectMapper.Map<TSource, TDestination> to use Mapperly, ensure your startup/host module registers Mapperly as the default object mapper:
context.Services.AddMapperlyObjectMapper();
 - If you keep AutoMapper as default, you’ll do the analogous AutoMapper default registration instead.
  • Framework design intent in ABP 10

    • ABP 10 moved its own modules to Mapperly (primarily due to AutoMapper’s licensing change), but ABP does not force you to remove AutoMapper immediately. Coexistence is explicitly possible because both integrations exist and ABP provides a migration guide.
  • Is coexistence “officially supported long-term” or only transitional?

    • ABP documents that it provides both integrations and offers migration steps. This supports the phased approach as a valid upgrade strategy.
    • From a maintenance standpoint, the long-term direction of the framework/modules is Mapperly, so it’s sensible to plan to gradually standardize on Mapperly when feasible.
  • Migration guidance / strategy for large AutoMapper profile bases (phased approach)

    1. Upgrade to ABP 10 and keep AutoMapper profiles working first (stabilize the upgrade).
    2. Introduce Mapperly for new mappings (don’t add new AutoMapper profiles).
    3. Migrate profile-by-profile using ABP’s migration guide:
      • Convert each AutoMapper profile into one or more Mapperly mappers (MapperBase<>, TwoWayMapperBase<>), then remove the corresponding AutoMapper maps.
    4. Keep mapping usage via ObjectMapper (ABP abstraction) where possible, and only inject concrete Mapperly mappers when you need very specific behavior.

Sources (validated)

  • https://abp.io/docs/10.0/release-info/migration-guides/abp-10-0
  • https://abp.io/docs/10.0/release-info/migration-guides/AutoMapper-To-Mapperly
  • https://abp.io/docs/latest/framework/infrastructure/object-to-object-mapping
  • https://abp.io/community/articles/l9f5ii8s

This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

  • In ABP, the HTTP request is not the “scope” that keeps DbContext/transactions alive; the Unit Of Work (UOW) is. ABP’s UOW defines the database connection/transaction boundary and disposes it when the UOW ends.
  • In a Blazor Server app, a user’s circuit is long-lived, but that should not mean your EF Core transaction stays open. It only happens if you create/keep a UOW open across multiple UI events (or you hold on to an EF IQueryable/DbContext-backed object and use it later).

What to do (recommended ABP approach)

  1. Do not inject repositories/DbContext and run EF code directly inside Blazor components.
    Keep components “UI only” and call Application Services (or domain services) instead.

  2. Ensure each operation is wrapped in its own UOW (short-lived).

    • ABP automatically creates a UOW around application service methods (via interceptor), so this is usually already handled when you call an app service from the component.
    • If you have a service method that is not an application service (or you disabled UOW conventions), explicitly use [UnitOfWork] or IUnitOfWorkManager.Begin(...) to scope it to that single method call.

    Example (explicit UOW):

public class MyBlazorActionService : ITransientDependency
   {
       private readonly IUnitOfWorkManager _unitOfWorkManager;
       private readonly IMyEntityRepository _repo;

       public MyBlazorActionService(IUnitOfWorkManager unitOfWorkManager, IMyEntityRepository repo)
       {
           _unitOfWorkManager = unitOfWorkManager;
           _repo = repo;
       }

       public async Task DoSomethingAsync()
       {
           await using var uow = _unitOfWorkManager.Begin(isTransactional: true);
           // db work here
           await uow.CompleteAsync();
       }
   }
  1. Never keep a transaction open waiting for user interaction.
    In Blazor it’s tempting to “start transaction on button A, commit on button B”. Don’t do that. Between those clicks you may block rows/tables (especially in PostgreSQL depending on what you touched). Instead:

    • design operations as single-command units (one UI event → one backend method → one UOW/transaction), or
    • use an application-level workflow (save draft / saga-like approach), not a single DB transaction spanning UI time.
  2. Avoid holding EF Core queryables across events.
    Don’t cache IQueryable, repositories, or anything that implicitly depends on an ambient UOW and then enumerate it later. Materialize results inside the same method/UOW (e.g., ToListAsync) and return DTOs to the component.

About your workaround

  • Creating a new scope per handler can work, but it’s not the intended pattern in ABP. The intended pattern is: Blazor component → call app service → app service method runs in its own UOW → done. That gives you the “per action” scope you want without manual service resolution.

  • https://abp.io/docs/latest/framework/architecture/domain-driven-design/unit-of-work


This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

Showing 21 to 30 of 892 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.2.0-preview. Updated on February 17, 2026, 09:10
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.