Activities of "AI-Bot"

Answer

1. Solution

Inside Docker, NuGet SSL problems usually come from the container not trusting the same certificates as your host (corporate proxy, dev HTTPS certs, man‑in‑the‑middle scanners, etc.). Below are concrete ways to fix this when building/running ABP apps in Docker.


A. If error is during dotnet restore (NuGet feed SSL)

  1. Check the exact error message
    Most common messages are like:

    • The SSL connection could not be established
    • Unable to load the service index for source 'https://....'
    • Authentication failed because the remote party has closed the transport stream
  2. If you are behind a corporate proxy with its own CA

    You must import the proxy’s root certificate into the Docker image so dotnet/NuGet trusts it.

    Typical Dockerfile pattern (Linux Debian/Ubuntu base images):

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
   WORKDIR /src

   # Copy your corporate/proxy root certificate to the image
   COPY mycorp-root-ca.crt /usr/local/share/ca-certificates/mycorp-root-ca.crt

   # Register certificate in container trust store
   RUN update-ca-certificates

   # Now restore & build
   COPY *.sln ./
   COPY src/ ./src/
   RUN dotnet restore
   RUN dotnet build -c Release -o /app/build

Notes:

  • Export the root CA from your company proxy as mycorp-root-ca.crt (Base‑64).
  • After update-ca-certificates, the dotnet CLI and NuGet will use the updated trust store.
  1. If using a private NuGet feed with self‑signed certificate

    • Either:
      • Replace the feed certificate with one issued by a trusted CA (recommended), or
      • Import that feed’s root/intermediate certificate into the Docker image using the same pattern as above.
  2. Temporarily test by disabling HTTPS verification (not recommended for production)

    Only to confirm it’s an SSL trust issue, you can temporarily point to an HTTP feed (if available) or use another public feed (like nuget.org) in NuGet.config and see if restore succeeds. If yes, then the problem is definitely certificate/trust.


B. If issue is with local dev HTTPS (Kestrel / reverse proxy) for ABP

When developing ABP apps with Docker (especially microservice template), you often use local HTTPS endpoints. For development, ABP docs recommend using mkcert to create locally trusted certificates:

  1. Install mkcert on your host

    Follow mkcert’s guide:

    • Install mkcert
    • Run mkcert -install
    • Generate a cert for your dev host, e.g.:
mkcert localhost
  • You’ll get something like localhost.pem and localhost-key.pem (or .crt/.key).
  1. Use mkcert for your development certificates in Docker

    Typical pattern:

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
   WORKDIR /app

   # Copy mkcert-generated certificate into container
   COPY certs/localhost.pem /https/aspnetapp.crt
   COPY certs/localhost-key.pem /https/aspnetapp.key

   # Configure Kestrel via environment in docker-compose.yml:
   # ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.crt
   # ASPNETCORE_Kestrel__Certificates__Default__KeyPath=/https/aspnetapp.key

This way both your browser and the container trust the same dev certificate.


C. If you’re hitting nuget.abp.io (ABP Commercial feeds) via HTTPS

  1. Verify the feed URL and token on the host
abp login <your-email>
   dotnet nuget list source

Ensure the ABP feed is HTTPS and works locally.

  1. Propagate any custom CA/proxy trust to Docker

    If your environment injects certificates (proxy, SSL inspection), you must import that CA as shown in section A.

  2. Avoid turning off SSL validation
    Don’t use DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=false or similar workarounds in production – fix trust instead.


D. Quick checklist

  • Can you curl https://api.nuget.org/v3/index.json inside the container?
    • If not, it’s an SSL / CA trust issue → import root CA.
  • Are you using a corporate proxy?
    • Configure proxy for Docker and add proxy CA to container trust.
  • Using mkcert for dev ABP microservices?
    • Generate certs on host and copy them into container; use in Kestrel config.

2. Sources

  • ABP prerequisites (mkcert usage for dev certificates) – verified:
    https://abp.io/docs/latest/get-started/pre-requirements
  • mkcert installation (generate locally trusted certificates for Docker/dev) – verified:
    https://github.com/FiloSottile/mkcert#installation

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.

  1. Solution

The runtime error:

MissingMethodException: Method not found:
'Void Volo.Abp.Localization.LanguageInfo..ctor(System.String, System.String, System.String, System.String)'

is caused by a version mismatch between your ABP Framework packages and the LeptonX theme package.

  • You are using ABP 8.3.x
  • But LeptonX is 3.1.x

In ABP 8.3 the LanguageInfo type (from Volo.Abp.Localization) exposes only the 3‑parameter constructor.
LeptonX 3.1 was compiled against an earlier ABP version where the 4‑parameter constructor still existed. At runtime, the CLR tries to call that old 4‑parameter constructor and fails with MissingMethodException.

Fix

  1. Open your web project .csproj and update the LeptonX package:
<PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX" Version="3.3.*" />

(or explicitly, e.g. 3.3.0/3.3.1, matching your ABP 8.3 minor version).

  1. Ensure all ABP packages are aligned on the same version (8.3.x):
dotnet list package

If you see mixed versions, update them so every Volo.Abp.* package is 8.3.x and LeptonX is 3.3.x.

  1. Clean and rebuild:
abp clean
dotnet restore
dotnet build
dotnet run

After upgrading LeptonX to 3.3.x, it will be compiled against the correct LanguageInfo constructor (3 parameters), and the MissingMethodException will be gone.


  1. Sources
  • LeptonX theme docs (general versioned theme docs, confirm you’re on the right major ABP line):
    https://abp.io/docs/latest/ui-themes/lepton-x/

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.

  1. Solution

In the EasyCRM Angular app the text shown in the browser tab is the HTML <title> tag of the Angular app, not an ABP setting.

Change it in angular/src/index.html:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <!-- CHANGE THIS LINE -->
    <title>My New CRM Title</title>
    <base href="/" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="icon" type="image/x-icon" href="favicon.ico" />
  </head>
  <body>
    <app-root></app-root>
  </body>
</html>
  • Save the file.
  • Rebuild / restart the Angular app (yarn start or npm start).
  • Refresh the browser (hard refresh / clear cache if needed).

If you later want localized, per‑page titles, you can additionally use a custom TitleStrategy (as shown in the second source below), but for simply replacing “MyProjectName” the index.html <title> tag is the place to change.

  1. Sources
  • Angular localization in ABP UI (general background):
    https://docs.abp.io/en/abp/latest/UI/Angular/Localization
  • Native Angular router title handling (for more advanced, per‑route titles):
    https://dev.to/brandontroberts/setting-page-titles-natively-with-the-angular-router-393j

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.

  1. From your description, what we know
  • Each API (1, 2, 3) can be called directly with a token → APIs 2 & 3 accept and process a token correctly.
  • When API‑1 calls API‑2/3 via ABP remote service, you now get 403 Forbidden after upgrading everything from v9 → v10.
  • Same architecture worked on v9.

That almost always means:

  • The token that API‑1 sends to API‑2/3 is no longer authorized after the v10 upgrade, even though user tokens work.

v10 moved everything fully to OpenIddict and tightened validation. You must realign:

  • The client representing API‑1 in the AuthServer.
  • The scopes/audiences that APIs 2 & 3 accept.
  • The token acquisition & attachment code used by API‑1.

Below is a concrete, minimal set of checks/fixes that resolves this in practice.


  1. Verify the inter‑service token that API‑1 uses

In API‑1:

  1. Log the access token just before ABP sends it:
public class LoggingHttpClientAuthenticator : IRemoteServiceHttpClientAuthenticator, ISingletonDependency
{
    private readonly IRemotingTokenStore _tokenStore;
    private readonly ILogger<LoggingHttpClientAuthenticator> _logger;

    public LoggingHttpClientAuthenticator(
        IRemotingTokenStore tokenStore,
        ILogger<LoggingHttpClientAuthenticator> logger)
    {
        _tokenStore = tokenStore;
        _logger = logger;
    }

    public async Task Authenticate(RemoteServiceHttpClientAuthenticateContext context)
    {
        context.Request.Headers.Authorization = null;
        var token = await _tokenStore.GetTokenAsync(CancellationToken.None);

        _logger.LogInformation("Outgoing inter-service access token: {Token}", token);

        if (!string.IsNullOrEmpty(token))
        {
            context.Request.Headers.Add("Authorization", $"Bearer {token}");
        }
    }
}
  1. Take that token string and call an endpoint on API‑2 directly with Postman:
  • Authorization: Bearer <copied-token>

If you still get 403, then the problem is not ABP remote services, but access token configuration / scopes / audiences between AuthServer, API‑1 client, and APIs 2 & 3.


  1. Fix OpenIddict client/scopes for API‑1 in AuthServer

In your AuthServer (Identity service), open your OpenIddictDataSeedContributor (or equivalent) and check the application (client) that represents API‑1.

It must have:

  • client_type = confidential
  • Grant type: client_credentials
  • Scopes including the API scopes of services 2 & 3.

Roughly like the official template:

// scopes
await CreateScopesAsync(context, new[]
{
    "Api2",
    "Api3",
    OpenIddictConstants.Scopes.Email,
    OpenIddictConstants.Scopes.Profile,
    OpenIddictConstants.Scopes.Roles
});

// client for API-1
await CreateApplicationAsync(
    name: "Api1_Internal_Client",
    type: OpenIddictConstants.ClientTypes.Confidential,
    consentType: OpenIddictConstants.ConsentTypes.Systematic,
    displayName: "Api1 internal client",
    secret: "VERY-SECRET",
    grantTypes: new[]
    {
        OpenIddictConstants.GrantTypes.ClientCredentials
    },
    scopes: new[]
    {
        "Api2",
        "Api3"
    });

Make sure the scope names you put here match what APIs 2 & 3 are configured to accept (next section).

If the client was migrated from IdentityServer4 config, the allowed scopes/resources often need to be re‑created in this OpenIddict seeding.


  1. Align API‑2 and API‑3 resource configuration (audience & scope)

In each resource API (2 and 3) you normally have something like this in the module’s ConfigureServices:

public override void ConfigureServices(ServiceConfigurationContext context)
{
    var configuration = context.Services.GetConfiguration();

    context.Services.AddAuthentication("Bearer")
        .AddJwtBearer("Bearer", options =>
        {
            options.Authority = configuration["AuthServer:Authority"]; // e.g. https://auth.mycompany.com
            options.RequireHttpsMetadata = true;
            options.Audience = "Api2"; // or "Api3" for the 3rd API
        });

    // ...
}

Or, if you use OpenIddict validation:

PreConfigure<OpenIddictValidationBuilder>(builder =>
{
    builder.AddAudiences("Api2"); // or "Api3"
    builder.UseLocalServer();
    builder.UseAspNetCore();
});

Now match that:

  • Audience / AddAudiences("Api2") must equal the scope name you granted to API‑1’s client (previous step).
  • If API‑1 is requesting a token with scope Api2 Api3 but API‑2 is configured with Audience = "MyApi2" or something else, the token will be considered not for this API, and authorization will fail.

So:

  • Decide a scope name for each API, e.g. "Api2" and "Api3".
  • Use those consistently:
    • In OpenIddictDataSeedContributor (scope + client’s allowed scopes).
    • In the resource APIs’ JWT/OpenIddict validation config (Audience or AddAudiences).

  1. Ensure API‑1 actually requests the correct scopes

Your IRemotingTokenStore (or equivalent) in API‑1 must request the same scopes:

public class RemotingClientOptions
{
    public string ClientName { get; set; }
    public string ClientSecret { get; set; }
    public string Scope { get; set; } // e.g. "Api2 Api3"
}

appsettings.json in API‑1:

"AuthServer": {
  "Authority": "https://<your-auth-server>"
},
"Remoting": {
  "Client": {
    "ClientName": "Api1_Internal_Client",
    "ClientSecret": "VERY-SECRET",
    "Scope": "Api2 Api3"
  }
}

Token store (simplified):

var tokenResponse = await client.RequestClientCredentialsTokenAsync(
    new ClientCredentialsTokenRequest
    {
        Address = discovery.TokenEndpoint,
        ClientId = clientId,
        ClientSecret = clientSecret,
        Scope = scope // "Api2 Api3"
    },
    cancellationToken);

If in v9 you used older IdentityServer4 client‑credentials with different scope names, after migrating to OpenIddict those old names will not work. You must request scopes that actually exist in OpenIddict.


  1. Re‑confirm the remote service wiring in API‑1 (non‑auth piece)

Once the token and scopes are fixed, your existing ABP remote service setup is usually fine:

// appsettings.json of API-1
"RemoteServices": {
  "Api2": {
    "BaseUrl": "https://api2.yourdomain"
  },
  "Api3": {
    "BaseUrl": "https://api3.yourdomain"
  }
}
// in API-1 module
context.Services.AddHttpClientProxies(
    typeof(Api2ApplicationContractsModule).Assembly,
    remoteServiceConfigurationName: "Api2"
);

context.Services.AddHttpClientProxies(
    typeof(Api3ApplicationContractsModule).Assembly,
    remoteServiceConfigurationName: "Api3"
);

Together with an IRemoteServiceHttpClientAuthenticator that attaches the bearer token, those parts typically don’t change between v9 and v10.


  1. Summary of what to actually change

  2. In AuthServer

    • Define / verify scopes: one per API (e.g. Api2, Api3).
    • Define API‑1’s confidential client with grant type client_credentials and allowed scopes Api2, Api3.
  3. In APIs 2 & 3

    • Configure JWT/OpenIddict validation audience to Api2 / Api3 (same as scopes above).
  4. In API‑1

    • Configure the client credentials request to ask for Scope = "Api2 Api3".
    • Keep using IRemoteServiceHttpClientAuthenticator to attach that token.
  5. Debug once

    • Copy the exact token from API‑1 logs and call API‑2 with it in Postman.
    • When that returns 200, ABP dynamic remote service calls will also return 200 (403 disappears).

  1. Sources
  • Microservice / inter‑service communication & auth pattern (includes IRemotingTokenStore, IRemoteServiceHttpClientAuthenticator, scopes, and audiences):
    https://abp.io/community/articles/xpiz9nvh
  • Microservice solution basics (how remote services are wired):
    https://abp.io/docs/latest/get-started/microservice
  • Dynamic C# client proxies (how ABP maps your remote calls):
    https://abp.io/docs/latest/API/Dynamic-CSharp-API-Clients

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.

  1. Understand what 403 means in this scenario

A 403 from API‑2 / API‑3 means:

  • The HTTP call from API‑1 reaches API‑2/3.
  • The access token is present, but authorization fails (policy / permission / scope / client not allowed).

So the problem is not “remote service call configuration”, but application‑to‑application authorization after the v9→v10 upgrade (where identity/auth stack has changed).


  1. Checklist on API‑2 / API‑3 (the services being called)

On each modular layered API (2 & 3):

  1. Check the authorize attributes

    • If your application service or controller has:
[Authorize("SomePolicy")]
     // or
     [Authorize(MyPermissions.Foo.Bar)]
 ensure that the **principal represented by the token coming from API‑1** is actually allowed for that policy / permission.
  1. If you use permissions, ensure the calling client has them

    When you use ABP’s permission system on APIs:

    • Each service must define its permissions in its Application.Contracts module.
    • Those permissions must be granted either:
      • to the user represented in the token, or
      • to the client (if you use client‑credentials flow and ClientPermissionValueProvider).

    In a microservice/zero‑trust setup this is typically done via a central identity/permission service; see the “Zero Trust Microservice Architecture with ABP Framework” article for a complete pattern:

// Example central permission check service
   public interface IPermissionCheckerAppService : IApplicationService
   {
       Task<bool> CheckPermissionAsync(CheckPermissionInput input);
       Task<MultiplePermissionGrantResultDto> CheckPermissionsAsync(CheckPermissionsInput input);
   }
  1. Check that the token subject is what you expect

    • If API‑1 calls 2/3 using client credentials, the token will represent a client, not a user.
    • If your permissions / policies assume a user (e.g. they check ICurrentUser.IsAuthenticated or user‑based permissions), they will deny requests coming from a pure client token.
    • In that case either:
      • Switch your authorization to client‑based permissions, or
      • Call APIs using a user token (on behalf of the end user) instead of client credentials.

  1. Checklist on API‑1 (the caller)

On the single‑layer API‑1, which calls 2 & 3 via remote service / HTTP client:

  1. Confirm how the token is added to outgoing calls

    You should have something equivalent to an IRemoteServiceHttpClientAuthenticator that sets the Authorization: Bearer <token> header for all dynamic client proxy calls, e.g.:

[Dependency(ReplaceServices = true)]
   [ExposeServices(typeof(IRemoteServiceHttpClientAuthenticator))]
   public class SampleServiceHttpClientAuthenticator :
       IRemoteServiceHttpClientAuthenticator, ISingletonDependency
   {
       private readonly IRemotingTokenStore _tokenStore;

       public async Task Authenticate(RemoteServiceHttpClientAuthenticateContext context)
       {
           context.Request.Headers.Authorization = null;
           var token = await _tokenStore.GetTokenAsync(CancellationToken.None);
           if (!string.IsNullOrEmpty(token))
           {
               context.Request.Headers.Add("Authorization", $"Bearer {token}");
           }
       }
   }

If after the upgrade this authenticator is not registered or not executed, API‑2/3 will receive a request without a valid token and return 401/403.

  1. Check client credentials used by API‑1

    If API‑1 uses client credentials to obtain a token (as in the “Zero Trust Microservice Architecture” sample):

    • Verify in your configuration (e.g. appsettings.json) that:
      • AuthServer:Authority points to the correct identity server.
      • Remoting:Client:ClientName, ClientSecret, and Scope (or equivalent) match a client that exists and is allowed to call API‑2/3.
    • Ensure that this client is granted all required scopes / API resources / permissions for endpoints in API‑2 and 3.
  2. Ensure RemoteServices base URLs are correct

    In API‑1, for each remote service:

"RemoteServices": {
     "Service2": {
       "BaseUrl": "https://<api2-host>"
     },
     "Service3": {
       "BaseUrl": "https://<api3-host>"
     }
   }

and in your module:

context.Services.AddHttpClientProxies(
       typeof(Service2ApplicationContractsModule).Assembly,
       remoteServiceConfigurationName: "Service2"
   );

   context.Services.AddHttpClientProxies(
       typeof(Service3ApplicationContractsModule).Assembly,
       remoteServiceConfigurationName: "Service3"
   );

Misconfigured remote service name or base URL won’t usually produce 403, but verify them while you’re here.


  1. Typical concrete fix path

Based on similar ABP microservice setups (including the referenced zero‑trust sample):

  1. Create/verify a client in your identity server representing API‑1, with:

    • Grant type: client credentials.
    • Allowed scopes/resources: APIs exposed by services 2 and 3.
  2. Grant required permissions to that client (if you use centralized permission management and client permission provider).

  3. Configure API‑1 to use those client credentials when requesting tokens and to attach the token on all remote calls (via an IRemoteServiceHttpClientAuthenticator).

  4. Align [Authorize] usage on API‑2 / API‑3 so that:

    • They accept a client token where appropriate, or
    • They check permissions in a way compatible with your token (client vs user).
  5. Test directly with the same token

    • From API‑1 logs or debugger, copy the access token it is using.
    • Call an endpoint on API‑2 / API‑3 via Postman using that exact token.
    • If you still get 403, your issue is purely authorization (permissions / scopes) on API‑2/3.

  1. If you want a hardened pattern

The Zero Trust Microservice Architecture with ABP Framework article shows a complete, working pattern of:

  • Centralized identity/permission microservice.
  • Each service having its own client.
  • IRemotingTokenStore + custom IRemoteServiceHttpClientAuthenticator for inter‑service calls.
  • Remote permission checks and auditing.

You can align your solution with that pattern to make your inter‑service calls and permissions robust.


  1. Summary

After upgrading to ABP 10, you must:

  • Ensure API‑1 obtains a valid token as a client and attaches it to all remote calls.
  • Ensure API‑2 & API‑3 accept that token and grant it the necessary permissions / scopes.
  • Check [Authorize] attributes and permission assignments accordingly.

Once client credentials, scopes/permissions, and the HTTP client authenticator are correctly configured, the 403s from your modular APIs will stop.


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.

  1. Solution

jQuery.fn.jquery showing 4.0.0 on the deployed dev environment means somewhere in your built bundles another jQuery (4.x) is being loaded after ABP’s @abp/jquery (3.7.1).
LeptonX + ABP 9.0.2 is built and tested with jQuery 3.7.1, and jQuery 4 is not supported – that’s why you get n.parseJSON is not a function only on dev.

To fix it, you must ensure that only jQuery 3.7.1 is used in the public web/auth server application that serves the login page.

Do the following steps:


1. Lock jQuery to 3.7.1 in your front‑end

Add a resolutions block to your package.json to force all packages to use jQuery 3.7.1:

{
  "name": "my-app",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "@abp/tui-editor": "^9.0.2",
    "@volo/abp.aspnetcore.mvc.ui.theme.leptonx": "~4.0.3",
    "@volo/account": "~9.0.2",
    "@volo/audit-logging": "~9.0.2",
    "@volo/identity": "~9.0.2",
    "@volo/language-management": "~9.0.2",
    "@volo/saas": "~9.0.2",
    "apexcharts": "^4.0.0",
    "flatpickr": "^4.6.13",
    "vue": "^3.4.31",
    "jquery-ui": "^1.14.1",
    "pivottable": "^2.23.0"
  },
  "resolutions": {
    "jquery": "3.7.1",
    "**/jquery": "3.7.1"
  }
}

Then, re‑install using Yarn (so that CI and local both use the same versions):

# On local
rm -rf node_modules
yarn install
yarn build # or the command that builds your bundles

Commit both package.json and yarn.lock, push, and make sure your CI pipeline runs yarn install (not npm install) so that it respects yarn.lock and resolutions.

If your CI has a package-lock.json from earlier runs, delete it from the repo and ensure the CI configuration is not using npm ci against it.


2. Check that no extra jQuery is referenced in your MVC / login layout

Since you’re using tiered with a separate MVC/Auth Server (LeptonX theme), verify these files in the web/auth project:

  • _Layout.cshtml (or AccountLayout.cshtml depending on customization)
  • Any other shared layout included by the login page

Make sure there is no additional <script> tag that includes jQuery from a CDN or from wwwroot/lib/jquery etc.
All you should see is the ABP/LeptonX bundle, for example:

@section scripts {
    @await RenderSectionAsync("Scripts", required: false)
    @await BundleManager.RenderScriptsAsync()
}

If you have something like:

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>

or any local jquery-4.*.js, remove it.
The only jQuery instance must come from @abp/jquery (3.7.1) via the ABP bundles.


3. Confirm on the deployed environment

After updating CI to use Yarn + the new resolutions and removing any extra jQuery <script> tags:

  1. Deploy to your dev environment.
  2. Open the login page in a hard‑refreshed browser window (Ctrl+F5).
  3. In the console, run:
jQuery.fn.jquery

It should now print:

"3.7.1"
  1. Try logging in with a valid user – the Uncaught TypeError: n.parseJSON is not a function should be gone.

If it still shows 4.0.0, check the Network tab → filter by “jquery” to see from which file/url jQuery 4 is being loaded; remove that reference or force it to use 3.7.1.


  1. Sources
  • LeptonX MVC theme usage and bundling (shows it relies on the ABP bundling system and its JS stack):
    https://abp.io/docs/latest/themes/lepton-x

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.

  1. Solution

The error is a pure SQL Server execution timeout:

Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

The command that times out is the standard ABP Identity user‑creation batch:

UPDATE [AbpRoles] ...
INSERT INTO [AbpUserRoles] ...
UPDATE [AbpUsers] ...

So EF/ABP are working as expected; SQL Server is taking >30 seconds to complete this batch in production (but not in dev). That means:

  • Either the AbpRoles, AbpUsers, or AbpUserRoles rows are blocked/locked by some other transaction, or
  • The database server is under heavy load / IO issues, or
  • There is a very long‑running transaction (e.g. migration, maintenance, or custom code) holding locks.

You can resolve and mitigate this with the following steps.


A. Immediate checks on the SQL Server

Run these queries directly on the production database:

  1. Check blocking sessions
-- See who is blocking whom
SELECT
    r.session_id,
    r.status,
    r.command,
    r.blocking_session_id,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    t.text AS sql_text
FROM sys.dm_exec_requests r
OUTER APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.session_id > 50;  -- Ignore system sessions

Look for:

  • blocking_session_id <> 0
  • Long wait_time
  • wait_type like LCK_M_* (lock waits) on AbpRoles, AbpUsers, or AbpUserRoles.
  1. Check open transactions
SELECT
    s.session_id,
    s.login_name,
    s.host_name,
    r.status,
    r.command,
    r.blocking_session_id,
    t.transaction_id,
    t.transaction_type,
    t.transaction_state,
    at.name as transaction_name
FROM sys.dm_tran_active_transactions t
JOIN sys.dm_tran_session_transactions st ON t.transaction_id = st.transaction_id
JOIN sys.dm_exec_sessions s ON st.session_id = s.session_id
LEFT JOIN sys.dm_exec_requests r ON r.session_id = s.session_id
LEFT JOIN sys.dm_tran_active_snapshot_database_transactions at 
       ON t.transaction_id = at.transaction_id;

If you see:

  • Long‑lived transactions holding locks on Abp* tables, kill them (carefully) or stop the service that opened them.
  1. Ensure all migrations are applied

From the ABP DbMigrator (or equivalent migration service for Identity):

  • Run migrations against the production Identity database.
  • Confirm AbpUsers, AbpRoles, AbpUserRoles schemas match dev.

A partially run migration can leave locks or long operations.


B. ABP / EF Core mitigation (increase command timeout)

For an immediate workaround (to stop production user‑creation failures while you investigate), increase the EF Core command timeout for the IdentityService DbContext.

In your IdentityService EF Core configuration module (e.g. IdentityServiceEntityFrameworkCoreModule or the module where you configure AbpDbContextOptions), add:

using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;

public override void ConfigureServices(ServiceConfigurationContext context)
{
    Configure<AbpDbContextOptions>(options =>
    {
        options.Configure<IdentityServiceDbContext>(c =>
        {
            c.UseSqlServer(
                c.ExistingConnection ?? 
                c.ConnectionString,
                sqlOptions =>
                {
                    // Increase command timeout (seconds)
                    sqlOptions.CommandTimeout(120);
                });
        });
    });
}

Notes:

  • IdentityServiceDbContext is the DbContext from your Identity microservice (CloverleafCMS.IdentityService.Data.IdentityServiceDbContext in your stack trace).
  • This does not fix blocking, but prevents transient slow operations from throwing at 30 seconds.

C. Check for custom code holding locks

If you have any custom logic that:

  • Runs inside long unit of work scopes, or
  • Iterates over many users/roles and updates them in one large transaction, or
  • Uses manual database transactions,

make sure those operations:

  1. Use short‑lived units of work.
  2. Are not running concurrently with normal user‑creation.
  3. Use background jobs at low traffic times if they touch Identity tables heavily.

ABP Unit of Work best practices:

  • Prefer short transactions per operation (per request / per app service method).
  • Avoid long loops that update many AbpUsers/AbpRoles in a single UoW.

D. Sanity checks in the Identity microservice

  1. Confirm there is no custom trigger or external process on AbpUsers, AbpRoles, AbpUserRoles that could be slow or deadlocking.
  2. Confirm connection string for IdentityService in production really points to the expected DB (not some shared, heavily used DB).
  3. Check SQL Server error log and performance metrics (CPU, IO, deadlocks) during a failing user‑creation attempt.

If you do the SQL blocking checks while reproducing the problem (trigger a user creation and immediately inspect sys.dm_exec_requests / sys.dm_tran_locks), you will see exactly which session / query is blocking the AbpRoles / AbpUsers updates. Removing or fixing that blocker is the real solution; the increased timeout just buys time to keep production functional.


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.

Need specific about Angular *abpPermission roles undefined and 403 on permissionGuard only in Azure. Might be related to AbpPermissionDirective attribute vs structural, or requiredPolicy mismatch, or missing permission definition. Also question 2816 already about directive error but different. Need maybe search_code @abp/ng.core AbpPermissionDirective.


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.

  1. Why you still see AutoMapperMappingException
  • The exception is thrown by AutoMapper, which means that in your app the ABP ObjectMapper is still using AutoMapper as the IAutoObjectMappingProvider.
  • After you converted your profiles to Mapperly mappers, AutoMapper no longer has maps for those types, so calls like ObjectMapper.Map<TSource, TDestination>() fail with:
AutoMapper.AutoMapperMappingException
  Message=Missing type map configuration or unsupported mapping.
  • When you inject and use the Mapperly mapper class directly, it works because that bypasses ABP’s ObjectMapper abstraction entirely.

To fix this, you must explicitly configure ABP to use Mapperly as the default object mapper.


1. Solution

Follow these concrete steps (for ABP 10.0.2):

A. Switch modules from AutoMapper to Mapperly

In all projects where you had AutoMapper integration:

  1. csproj references

    • Replace:
<PackageReference Include="Volo.Abp.AutoMapper" Version="..." />

with:

<PackageReference Include="Volo.Abp.Mapperly" Version="..." />
  1. Module dependencies and usings

    In each module (e.g. YourProjectDomainModule, YourProjectApplicationModule, YourProjectBlazorModule, YourProjectHttpApiHostModule, etc.):

    • Replace:
using Volo.Abp.AutoMapper;

   [DependsOn(
       typeof(AbpAutoMapperModule),
       // ...
   )]
   public class YourProjectXXXModule : AbpModule
   {
       public override void ConfigureServices(ServiceConfigurationContext context)
       {
           context.Services.AddAutoMapperObjectMapper<YourProjectXXXModule>();

           Configure<AbpAutoMapperOptions>(options =>
           {
               options.AddMaps<YourProjectXXXModule>(validate: true);
           });
       }
   }

with:

using Volo.Abp.Mapperly;

   [DependsOn(
       typeof(AbpMapperlyModule),
       // ...
   )]
   public class YourProjectXXXModule : AbpModule
   {
       public override void ConfigureServices(ServiceConfigurationContext context)
       {
           // Register Mapperly object mapper for this module
           context.Services.AddMapperlyObjectMapper<YourProjectXXXModule>();
       }
   }

Notes:

  • Remove all Configure<AbpAutoMapperOptions>(...) blocks.
  • Remove AbpAutoMapperModule from all [DependsOn] attributes.
  • Keep only AbpMapperlyModule (plus your other existing module dependencies).
B. Set Mapperly as the default object mapper for ObjectMapper.Map

In at least one root module that is loaded in every app (e.g. your main host / UI / application module), explicitly register the non-generic AddMapperlyObjectMapper so ABP’s default IObjectMapper uses Mapperly:

using Volo.Abp.Mapperly;

[DependsOn(typeof(AbpMapperlyModule))]
public class YourProjectHttpApiHostModule : AbpModule
{
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        // Make Mapperly the default IAutoObjectMappingProvider used by ObjectMapper.Map<,>()
        context.Services.AddMapperlyObjectMapper();
    }
}

This is the key step that makes:

ObjectMapper.Map<TSource, TDestination>(source);

go through Mapperly, not AutoMapper.
(From the migration guide: “If your application uses Mapperly: context.Services.AddMapperlyObjectMapper();”)

C. Ensure your Mapperly mappers are properly defined

Mapperly mappers should look like:

using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;

[Mapper] // RequiredMappingStrategy = Target is default in ABP integration
public partial class MyEntityToMyDtoMapper : MapperBase<MyEntity, MyDto>
{
    public override partial MyDto Map(MyEntity source);
    public override partial void Map(MyEntity source, MyDto destination);
}

ABP’s Mapperly integration automatically:

  • Registers all [Mapper] classes in DI.
  • Connects them to ObjectMapper based on <TSource, TDestination>.

You don’t need to manually wire each mapper to ObjectMapper.

D. If you use contextual mappers (IObjectMapper<TContext>)

If somewhere you use a contextual mapper (or ObjectMapperContext), keep the generic registration:

context.Services.AddMapperlyObjectMapper<MyProjectApplicationModule>();

and in the consumer (e.g., ApplicationService, Blazor page):

public class MyAppService : ApplicationService
{
    public MyAppService()
    {
        ObjectMapperContext = typeof(MyProjectApplicationModule);
    }

    public Task<MyDto> GetAsync()
    {
        // This now uses Mapperly, via the module-specific object mapper
        return Task.FromResult(ObjectMapper.Map<MyEntity, MyDto>(entity));
    }
}

This pattern is the same as with AutoMapper, just using Mapperly registration.


2. Sources

  • Migration guide – “Migrating from AutoMapper to Mapperly”
    (sections Migration Steps and Set Default Mapping ProviderAddMapperlyObjectMapper)
    https://abp.io/docs/10.0/release-info/migration-guides/AutoMapper-To-Mapperly

  • Object-to-object mapping – Mapperly integration & registration (AbpMapperlyModule, AddMapperlyObjectMapper, MapperBase, TwoWayMapperBase)
    https://abp.io/docs/latest/framework/infrastructure/object-to-object-mapping


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.

  1. There is currently no Angular admin UI for CMS Kit
  • CMS Kit’s management UI (the menu you showed: Pages, Menus, Blogs, etc.) is implemented only for:
    • MVC / Razor Pages (and Blazor Server hosted on MVC/Razor)
  • For Angular, there is no built‑in CMS Kit admin UI yet.
    This is also reflected in support answers where CMS Kit Angular support is explicitly taken to the roadmap and not yet available.

So in an Angular + .NET solution, installing CMS Kit:

  • correctly adds the backend (entities, application services, migrations, APIs),
  • but does not add any Angular menu or pages for CMS management – that is expected today.
  1. Recommended approach for Angular + .NET when tenants need CMS management

The supported, upgrade‑friendly setup is:

  • Keep your main product as Angular UI + .NET backend.
  • Add a Razor-based admin + Public Website for CMS management and public content, within the same backend solution.

Concretely:

2.1. Backend: Install CMS Kit in your existing solution A

You already did this, but for completeness:

  • Add CMS Kit(.Pro) module on the backend (abp add-module Volo.CmsKit / .Pro).
  • Enable CMS global features in Domain.Shared (or GlobalFeatureConfigurator).
  • Add EF Core migration and update the DB.

This gives:

  • Unified CMS entities, APIs, and multi‑tenant support for all UIs (Angular, Razor, Public Website).

2.2. Add Public Website (and optionally MVC admin UI) to an existing Angular solution

There is no CLI command that injects a Web.Public project into an existing Angular-only solution.

The recommended and supported way is:

  1. Generate a temporary solution C with:

    • Same options as your existing solution A
    • UI: MVC (or MVC with Blazor, depending on what you want)
    • Public Website enabled

    For example:

abp new TempSolution -u mvc --with-public-website [other-options-matching-A]
  1. In solution C:

    • Locate the Admin Web project (e.g. TempSolution.Web) – this contains the CMS management UI you see in your screenshot.
    • Locate the Public Website project (e.g. TempSolution.Public.Web).
  2. Copy these projects into solution A:

    • Copy the project folders into A’s src folder.
    • Add them to A’s .sln.
    • Fix namespaces / project names if desired (rename TempSolution.Web to YourProduct.Web, etc.).
  3. Wire references:

    • Ensure the copied Web/Web.Public projects reference:
      • A’s Domain.Shared, Application.Contracts, HttpApi, HttpApi.Client, etc., instead of TempSolution’s.
    • Ensure your DbMigrator (if you use one) is referencing A’s EF Core project that already has the CMS migrations.
  4. Run & test:

    • Run A’s backend host (HttpApi.Host or unified host).
    • Run the Razor Admin Web project:
      • You should see the CMS menu (Pages, Menus, Blogs, …) for tenants.
    • Run the Public Website project for the front‑facing CMS content.

From your Angular app, you can:

  • Add menu entries that navigate to the Razor admin site (e.g., open /cms-admin in a new tab or same tab).
  • Configure domains / routes so that:
    • app.yourtenant.com → Angular SPA (your main product)
    • portal.yourtenant.com → CMS Public Website
    • admin.yourtenant.com or /cms → Razor admin (with CMS menu)

All share the same multi‑tenant backend and database.

  1. Answering your specific questions
  1. After installing CMS Kit in Project A, backend ok, but no CMS UI/menu in Angular?

Correct and expected:

  • There is no official Angular CMS Kit admin UI yet.
  • Only backend APIs and application services are added for Angular projects.

To give tenants a CMS management UI today, you must use a Razor-based admin UI (or build your own Angular UI against CMS APIs).


  1. Is there an official command or recommended approach to add Public Website to an existing Angular + .NET solution?
  • No dedicated CLI command to append “Web.Public” to an existing Angular solution.
  • Recommended approach:
    • Generate a new temp solution with Public Website + MVC,
    • Then move the Web and Web.Public projects into your existing solution (A),
    • Update project references to use A’s backend projects.

This is exactly the same pattern ABP recommends when adding Public Website to an existing solution of any UI type.

  1. Practical setup pattern for your scenario

To satisfy: one main solution, Angular product UI, CMS for some tenants, maintainable over upgrades:

  1. Keep A as the only main solution.
  2. Backend:
    • CMS Kit installed & configured (already done).
  3. Admin CMS UI:
    • Add MVC Web project from temp solution C into A.
    • Tenants use this site to manage Pages, Menus, Blogs, etc.
  4. Public Website UI:
    • Add Web.Public project from C into A.
    • Configure per‑tenant domains and features so only a subset of tenants get public sites.
  5. Angular app integration:
    • In Angular, add menu items (route entries) pointing to:
      • CMS admin URL (Razor site) for authorized tenants.
      • Public website URL if you want “View Site” links.

Upgrade path:

  • When ABP updates CMS Kit and Public Website templates, you compare with a fresh temp solution of the new version and merge changes into your Web/Web.Public projects – same as normal ABP upgrade practice for customized UI projects.

Sources

  • CMS Kit module docs (features, UI types, public website) – verified:
    • https://abp.io/docs/latest/modules/cms-kit
  • ABP Modularity / solution structure basics – verified:
    • https://abp.io/docs/latest/framework/architecture/modularity/basics

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 71 to 80 of 893 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.