Activities of "AI-Bot"

  • ABP 10.1.1 still uses AbpOpenIddictWildcardDomainOptions the same way: WildcardDomainsFormat must contain only the domain/root format, not callback paths.
  • In other words, remove these lines (they can cause mismatches after upgrade because ABP/OpenIddict compares and expands URIs based on the “root format” you give it):
    • ... + "signin-oidc"
    • ... + "signout-callback-oidc"

Use this configuration instead:

using Volo.Abp.OpenIddict.WildcardDomains;

if (!hostingEnvironment.IsDevelopment() &&
    !string.IsNullOrWhiteSpace(configuration["App:OpenIddictWildcardDomainsFormat"]))
{
    PreConfigure<AbpOpenIddictWildcardDomainOptions>(options =>
    {
        options.EnableWildcardDomainSupport = true;
        options.WildcardDomainsFormat.Add(configuration["App:OpenIddictWildcardDomainsFormat"]!);
    });
}

And set the value without a trailing slash:

"App": {
  "OpenIddictWildcardDomainsFormat": "https://{0}.<app-domain>"
}

Also (common after moving to AKS/ingress): ensure your apps read the correct external scheme/host; otherwise OpenIddict may generate/validate redirect URIs against the wrong scheme/host. In AKS, configure forwarded headers / ingress so the app sees https and the real public host.

Sources:

  • https://abp.io/docs/10.1/guides/ms-multi-tenant-domain-resolving
  • https://abp.io/docs/latest/guides/ms-multi-tenant-domain-resolving
  • https://abp.io/docs/latest/framework/architecture/multi-tenancy/index#domain-subdomain-tenant-resolver

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 10, you should not add signin-oidc / signout-callback-oidc variants into WildcardDomainsFormat. WildcardDomainsFormat expects site root URL formats, not callback endpoints.
  • Use a wildcard domain format without the trailing slash, and only for the host part, e.g.:
"App": {
  "OpenIddictWildcardDomainsFormat": "https://{0}.<app-domain>"
}
  • Configure it like this (only add the root format):
using Volo.Abp.OpenIddict.WildcardDomains;

if (!hostingEnvironment.IsDevelopment() &&
    !string.IsNullOrWhiteSpace(configuration["App:OpenIddictWildcardDomainsFormat"]))
{
    PreConfigure<AbpOpenIddictWildcardDomainOptions>(options =>
    {
        options.EnableWildcardDomainSupport = true;
        options.WildcardDomainsFormat.Add(configuration["App:OpenIddictWildcardDomainsFormat"]!);
    });
}
  • After deploying, ensure the AuthServer/OpenIddict client redirect URIs that are seeded/created are consistent with your public URLs (scheme/host). If you are behind an ingress/reverse proxy, also ensure forwarded headers are configured so the generated redirect URLs use https and the public host (otherwise you can end up with mismatched redirect/callback URLs causing 404/redirect issues in tenant subdomains).

Links:

  • https://abp.io/docs/latest/guides/ms-multi-tenant-domain-resolving
  • https://abp.io/docs/10.4/guides/ms-multi-tenant-domain-resolving

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.

Answer
  • UI Options (Blazorise / MudBlazor) are available for Blazor solutions, but ABP Studio v3.0.3 currently shows the “UI Options” step only for the “Modern” solution template.

  • When you create a solution with the Classic template (as in your screenshot), ABP Studio doesn’t display that UI Options screen for Blazor; it proceeds without that selection. This is a Studio wizard capability difference (not an ABP Framework 10.4.0 limitation).

  • If you want to pick the Blazor component library explicitly, you can:

    1. Create the solution using the Modern template in ABP Studio (then you should see Blazorise/MudBlazor options), or
    2. Create via ABP CLI and set the Blazor UI library with the CLI option mentioned in the docs (Blazorise vs MudBlazor).

Sources:

  • https://abp.io/docs/10.4//ui-themes/
  • https://abp.io/docs/10.4//studio/release-notes
  • https://abp.io/docs/10.4//framework/ui/blazor/overall

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 abp global tool is running from ~/.dotnet/tools/abp and is using the .NET runtime located at ~/.dotnet (see “.NET location: /home/xx/.dotnet”).
  • In that ~/.dotnet location you only have .NET 8 and .NET 9 runtimes, so the tool fails when it looks for Microsoft.NETCore.App 10.0.0.
  • Meanwhile your .NET 10 SDK/runtime is installed under /usr/share/dotnet, which is not the runtime location your tool is picking up.

Fix (recommended): make the tool use the system dotnet

  1. Ensure your shell uses /usr/share/dotnet (system install) instead of ~/.dotnet:
which dotnet
dotnet --info
  1. If which dotnet points to ~/.dotnet/dotnet, fix your PATH so /usr/share/dotnet is first (example for bash):
export DOTNET_ROOT=/usr/share/dotnet
export PATH=/usr/share/dotnet:$PATH
hash -r
  1. Reinstall/update ABP CLI using the same dotnet you’ll run it with:
dotnet tool uninstall -g Volo.Abp.Studio.Cli
dotnet tool install -g Volo.Abp.Studio.Cli
# or:
# dotnet tool update -g Volo.Abp.Studio.Cli
  1. Run:
abp -h

Alternative fix: install .NET 10 runtime into ~/.dotnet

If you intentionally want to use the per-user dotnet (~/.dotnet), then you must install the .NET 10 runtime into that same location so ~/.dotnet/shared/Microsoft.NETCore.App/10.x exists. (Right now it doesn’t, according to your error output.)

Why this happens

The ABP CLI is a .NET global tool and it runs on the runtime selected by the dotnet resolution / DOTNET_ROOT / PATH. In your case the tool host resolves to ~/.dotnet, which doesn’t contain .NET 10.

Links (validated):

  • ABP CLI install/update commands: https://abp.io/docs/latest/cli/
  • .NET error explanation (“You must install or update .NET…”): https://aka.ms/dotnet/app-launch-failed

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.

  • azure_ad_token is not a grant type supported by ABP’s Auth Server (OpenIddict) out of the box. When /connect/token returns unsupported_grant_type, it means the authorization server doesn’t have that grant enabled/implemented.
  • For mobile-based Microsoft (Azure AD) SSO, the expected OAuth/OIDC approach is typically:
    1. The mobile app signs in against Azure AD using Authorization Code Flow with PKCE and receives an authorization code from Azure AD (not an ABP AuthServer code).
    2. Then your backend either:
      • uses Azure AD as an external login provider (recommended), where the user signs in via the normal ABP UI endpoints (browser-based), or
      • you implement a custom OpenIddict extension grant on the ABP AuthServer to exchange an Azure AD token for an ABP access token (advanced scenario).

What to do in ABP (recommended / standard)

  1. Configure Azure AD as an external OpenID Connect provider in your ABP AuthServer / Web (tiered: in the AuthServer/IdentityServer project), using AddOpenIdConnect (or AddMicrosoftIdentityWebApp).
  2. In the mobile app, open the ABP AuthServer’s login (hosted UI) in a system browser (or in-app browser with proper redirect handling). This keeps ABP in control of the OpenID Connect flow and cookie/external login pipeline.

This is why it “works on web”: the web flow is usually going through the interactive external login pipeline, not a custom /connect/token exchange with grant_type=azure_ad_token.

If you insist on “Azure AD token -> ABP token” (custom grant)

If your Flutter app already gets an Azure AD token and you want to exchange it at https://authserver.../connect/token, then you must do both:

  1. Implement a custom OpenIddict extension grant on the AuthServer (so the server understands grant_type=azure_ad_token and validates the incoming Azure AD token).
  2. Allow that grant type for the specific OpenIddict client (XXX_MobileApp) in your AuthServer’s data seed (client permissions). Otherwise you’ll get either unsupported_grant_type or unauthorized_client.

In ABP/OpenIddict, allowed grant types are configured per client during seeding (e.g., adding OpenIddictConstants.GrantTypes.AuthorizationCode, RefreshToken, etc.). Custom grants must also be included there, and the client may need to be re-created/re-seeded if it already exists.

Web vs Mobile differences (why only mobile fails)

  • Your web client is likely using a client configured for authorization_code (and the external login UI), which ABP supports by default.
  • Your mobile client is using grant_type=azure_ad_token, but:
    • ABP/OpenIddict doesn’t support it by default (server-side missing), and/or
    • the mobile OpenIddict client (XXX_MobileApp) does not have permission for that grant (client-side missing in OpenIddict application configuration).

Sources

  • https://abp.io/docs/latest/modules/openiddict
  • https://abp.io/community/articles/how-to-use-the-azure-active-directory-authentication-for-mvc-razor-page-applications-4603b9cf
  • https://abp.io/community/articles/lyk87w5l

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 Studio v3.x, the AI Agent is still a probabilistic tool (LLM-based). For “framework-shaped” tasks (like extending Setting Management UI with contributors/components), it can drift into non-existing types/namespaces (e.g., inventing SettingManagementViewComponent) and then spiral while trying to self-fix—burning credits. This is an expected failure mode for agentic coding when the task requires exact ABP API usage and project-specific conventions.

  • To improve success rate and reduce wasted credits, use the agent the way it was designed to be most deterministic:

    1. Run Analyze on the solution and re-run it after any significant change, so the agent has the correct structural map (projects, modules, ABP roles).
    2. Prefer Ask mode first to have it locate the exact existing ABP extension points in your solution (e.g., where SettingManagementPageOptions is configured in your Web module) before letting it generate code.
    3. Use Plan mode but require it to reference existing types/paths found in your solution (e.g., “use the same pattern as the existing Setting Management contributors already in this solution”).
    4. Use Custom Workflows so builds/restarts happen deterministically after each agent iteration (this prevents long “try/fix” loops and makes failures obvious quickly).
    5. Keep agent tasks small and verifiable (one ABP integration point per run): e.g. “only add the setting group contributor + registration” (build), then “only add the view component + Razor view” (build), then “wire up permissions/menu” (build).
    6. When it makes a repeated mistake, save a Lesson (ABP Studio supports this) such as: “Do not invent ABP types; search the solution for existing Setting Management contributor examples and copy the pattern.”
  • For cost control:

    • Stop the agent as soon as it introduces compile errors that indicate hallucinated APIs (wrong base class, missing namespaces). Switch back to Ask mode and force it to first find the correct ABP classes in the current solution and only then proceed.
    • Avoid asking it to do an end-to-end feature in one go; that’s the most credit-expensive path.
  • If you believe this is a product-quality issue with ABP Studio AI Agent v3.0.2 (e.g., consistent failure even with Analyze + small scoped tasks), please contact us so the team can review logs/session behavior: https://abp.io/contact

Less obvious references (verified):

  • https://abp.io/studio/ai-agent
  • https://abp.io/docs/10.2/studio/overview
  • https://abp.io/community/articles/o1ni0toc

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 doesn’t require you to “replace an application service” to integrate SAML. Treat SAML as another ASP.NET Core authentication handler (like any social/OIDC provider), then let ABP’s Account login page flow (external login) create/link the ABP user and sign them in.

  • The wiring point is in your host web module where authentication is configured (e.g., *.Web for MVC/Razor UI or *.HttpApi.Host / separate AuthServer host in tiered setups): you register the SAML scheme via AddAuthentication().AddXxx(...) and ensure its SignInScheme is IdentityConstants.ExternalScheme so ABP’s external-login pipeline can read it.

  • Once that’s done, ABP will handle:

    • External challenge/redirect
    • Reading external identity on callback
    • Creating/linking the ABP user (if enabled by your account module configuration)
    • Issuing the application cookie / tokens (OpenIddict in your case)
  • To support multiple login types:

    1. SAML (Salesforce): register a SAML authentication scheme (ComponentSpace) as an external provider (must use IdentityConstants.ExternalScheme).
    2. ABP OpenIddict: keep it as your main auth server/token issuer (vendors can still use local username/password or any other configured provider).
    3. Social logins: register them the same way (external schemes) alongside SAML. ABP’s login UI will list them.
  • About “customizing Volo.Abp.Identity” with Team license / no commercial source:

    • Do not fork/modify Volo.Abp.Identity and reference it alongside the NuGet package; that will create assembly conflicts (duplicate types/assemblies).
    • The supported approach is to customize behavior via extension points in your own module/application (e.g., adding an external auth scheme, overriding options, adding claims, etc.), not by shipping a modified Volo.Abp.* assembly.
    • If you need license/commercial source-code related guidance or entitlements, contact ABP via: https://abp.io/contact

(Links validated: https://abp.io/community/articles/4603b9cf , https://abp.io/docs/latest/solution-templates/layered-web-application/authentication , 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.

Answer
  • Configure<AbpMultiTenancyOptions>(o => o.IsEnabled = false) only disables ABP’s multi-tenancy behavior at runtime (tenant resolution, multi-tenancy checks/filters, etc.). It does not automatically uninstall modules, and it does not remove:

    • SaaS/Tenant/Edition UI pages & menus (those come from the SaaS module and/or your menu configuration),
    • Web API endpoints provided by those modules,
    • DB tables created by those modules (already created tables remain unless you remove the module and regenerate migrations).
  • If your goal is “B2C, and the customer must not be able to turn it into SaaS later”, the recommendation is to remove the SaaS module completely from the solution:

    1. Remove SaaS module NuGet packages (and any SaaS-related module dependencies) from your .csproj files.
    2. Remove SaaS module DependsOn(...) entries from your module classes (Web/HttpApi/EntityFrameworkCore/etc.).
    3. Remove SaaS EF Core model configuration from your DbContext (builder.ConfigureSaas();) if it exists.
    4. Remove SaaS menu contributions (SaaS menu group, Tenant/Edition items) if you added any custom ones.
    5. Create a new EF Core migration after removing the module so the migration will drop the SaaS tables (or, if you prefer, you can manually remove them, but migrations are the safer/trackable way).
    6. Rebuild/run: the UI and endpoints won’t exist because the module is not in the app anymore, and DB schema will be updated by migrations.
  • Also note: if the client has host admin + direct DB access, they can always change data in any table (including permissions/features/settings). The only robust way to prevent SaaS capabilities from being enabled is not shipping the SaaS module/code at all (steps above). Disabling multi-tenancy via IsEnabled=false doesn’t provide that guarantee.

(Links checked)

  • https://abp.io/docs/latest/framework/architecture/multi-tenancy/
  • https://abp.io/support/questions/1795

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 resource-based authorization does not support “filter operators/conditions configured from UI” (e.g., Order.UserId == CurrentUser.Id or Vendor.UserId == CurrentUser.Id) as part of the built-in permission management UI.

    • The built-in UI for resource-based authorization is for granting permissions to specific resource instances (per record) to users/roles/clients, not for defining predicate/DSL-style rules.
  • For your legacy rules (ownership / “self” access) you should implement them with code-enforced policies, typically in one of these ABP-native ways:

    1. Tenant isolation (already built-in)

      • Ensure your entities implement IMultiTenant (or otherwise have TenantId) so ABP automatically isolates data per tenant.
    2. Ownership / “self” access (recommended: data filter + app service checks)

      • Model ownership explicitly (e.g., Order.CreatorId or Order.CustomerUserId, Vendor.OwnerUserId).
      • Enforce with:
        • AuthorizationService.CheckAsync(resource, permissionName) only if you are using per-record grants, OR
        • Plain application service checks (e.g., compare entity’s owner id with CurrentUser.Id) for “self-service” rules.
      • If you want this enforced at query level (so users only see their own rows), implement a custom filtering approach (commonly done by applying Where(...) based on CurrentUser.Id in repositories/app services). ABP’s built-in “data filters” are designed around known filter concepts (like multi-tenancy/soft-delete), not an end-user-configurable query builder for arbitrary entities.
    3. If you truly need a UI like your screenshot (a rule builder)

      • That is a custom feature you need to build (store rules in DB, build UI, parse/evaluate rules, translate them into LINQ/SQL, and enforce them consistently).
      • ABP does not ship an out-of-the-box “authorization rule query builder UI” that plugs into permissions.
  • If your goal is “Customer can edit only their own orders” and “Vendor can access only their own vendor profile”, the clean ABP approach is:

    • Keep permissions coarse (e.g., Orders.Edit, Vendors.ViewSelf)
    • Enforce ownership constraints in the corresponding application service methods (or a domain service), e.g.:
      • Load entity
      • Check permission
      • Check entity.UserId == CurrentUser.Id (and tenant is already isolated)

Sources (verified):

  • https://abp.io/docs/10.4/framework/fundamentals/authorization/resource-based-authorization
  • https://abp.io/docs/latest/framework/fundamentals/authorization/resource-based-authorization
  • https://abp.io/docs/latest/framework/fundamentals/authorization

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.

  • This is a known timing/regression issue in LeptonX 5.3.x (ABP 10.3.x): the side-menu JS initializer (initSideMenu) can run when #lpx-sidebar exists but before the real menu items are rendered (or after Blazor later replaces them, e.g., on app configuration changes / impersonation). In that case, LeptonX binds zero click handlers, so parent items don’t expand. Your DevTools observation matches this exactly: menuItems is empty until you manually call createMenuItems() / re-init.

  • Your TelerikRootComponent placement is not the root cause. The issue is that LeptonX side menu binding is done once on first render, and if the DOM changes later, handlers can be lost. (So moving Telerik “above Routes” is not required just for this.)

Workaround (until you update to a LeptonX patch that fixes it)

Add a small script that re-runs only the side-menu initializer once the sidebar items appear (or re-appear) after Blazor updates the DOM.

  1. Create wwwroot/lpx-sidebar-rebind-polyfill.js (Server UI project that serves _Host.cshtml / static files):
(function () {
  'use strict';

  const DONE_ATTR = 'data-lpx-polyfill-rebound';

  function tryRebind() {
    const sidebar = document.querySelector('#lpx-sidebar');
    if (!sidebar) return false;

    // Wait until real items exist
    if (!sidebar.querySelector('.outer-menu-item > .lpx-menu-item')) return false;

    // Prevent endless re-binding loops
    if (sidebar.hasAttribute(DONE_ATTR)) return true;
    sidebar.setAttribute(DONE_ATTR, '');

    const initFn =
      window.leptonx &&
      window.leptonx.init &&
      window.leptonx.init.initializers &&
      typeof window.leptonx.init.initializers.get === 'function' &&
      window.leptonx.init.initializers.get('initSideMenu');

    if (typeof initFn === 'function') {
      initFn(); // binds expand/collapse handlers
      return true;
    }

    return false;
  }

  function start() {
    if (tryRebind()) return;

    const obs = new MutationObserver(() => {
      if (tryRebind()) obs.disconnect();
    });

    obs.observe(document.body, { childList: true, subtree: true });

    // safety stop
    setTimeout(() => obs.disconnect(), 30000);
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', start);
  } else {
    start();
  }
})();
  1. Reference it after the LeptonX global script bundle in _Host.cshtml:
<abp-script-bundle name="...LeptonX...Global" />
<script src="~/lpx-sidebar-rebind-polyfill.js"></script>

This ensures that when the menu DOM is finally present (or re-rendered), initSideMenu runs against the final nodes and the parent items expand reliably.

Sources

  • https://abp.io/support/questions/10622
  • https://abp.io/support/questions/10642

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 231 to 240 of 1374 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 October 21, 2026, 11:09
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.