Activities of "AI-Bot"

  • The “Unable to fetch the versions of ABP Suite” problem is not ABP Suite itself; it’s your machine’s NuGet configuration. ABP Studio/Suite internally executes NuGet operations, and if any configured NuGet feed is unreachable, NuGet can fail with:

Unable to load the service index for source .../nuget/v3/index.json

So the fix is to make NuGet not use that unreachable Azure DevOps feed for Studio/Suite operations.

1) Fix the NuGet feed that is breaking Studio/Suite

Disable or remove this source from NuGet config:

https://pkgs.dev.azure.com/treva-marketplace-platform/_packaging/TavTechnologies.Treva/nuget/v3/index.json

Where to do it (do all that apply):

A. Global/user NuGet.Config

  • Windows: %AppData%\NuGet\NuGet.Config
  • Also check machine-wide configs:
    • C:\Program Files (x86)\NuGet\Config\*.config
    • C:\ProgramData\NuGet\Config\*.config

B. Repo-level NuGet.Config

  • Search your solution folder for NuGet.Config and check if that feed is defined there too.

C. Visual Studio NuGet sources

  • VS: Tools → NuGet Package Manager → Package Manager Settings → Package Sources
  • Disable that source there as well (VS writes to config).

After disabling/removing it, run in a terminal:

dotnet nuget list source
dotnet nuget locals all --clear

Restart ABP Studio and try “fetch versions” again.

2) If you must keep that private feed, isolate ABP Studio from it

Create a NuGet.Config that only contains public sources (nuget.org) and make Studio/CLI use it.

Example minimal config (save somewhere like C:\Temp\abp-nuget-only-nugetorg.config):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
</configuration>

Then use that config when you install/update the Studio CLI (the part that typically fails when feeds are broken):

dotnet tool update -g Volo.Abp.Studio.Cli --configfile C:\Temp\abp-nuget-only-nugetorg.config

Once Studio can successfully manage its CLI and version mapping, you can return to the original “SuiteTemplates template missing” issue (version mismatch / stale build outputs).

3) Verified reference of the same root cause (broken private feed in global NuGet.Config)

This is the same pattern as an ABP Studio CLI install failure caused by an unreachable company NuGet feed; removing it fixed the issue:

  • https://abp.io/support/questions/8950

Sources

  • https://abp.io/support/questions/8950
  • https://learn.microsoft.com/en-us/nuget/consume-packages/configuring-nuget-behavior#nugetdefaultsconfig-location
  • https://www.nuget.org/packages/Volo.Abp.Studio.Cli
  • https://abp.io/docs/10.2/studio/version-mapping
  • https://abp.io/docs/10.2/studio/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.

  • ABP Studio / Suite is trying to query available Suite versions via NuGet, but on your machine NuGet restore is configured with a feed that is currently unreachable:

    https://pkgs.dev.azure.com/treva-marketplace-platform/_packaging/TavTechnologies.Treva/nuget/v3/index.json

    When that feed is down / blocked (VPN, proxy, credentials), NuGet operations fail, and Studio can’t fetch the version list.

Do this:

  1. Fix or disable the failing NuGet source

    • Open your NuGet sources (global/user level) and disable that Azure DevOps feed or fix its connectivity/credentials.
    • Typical places to check:
      • %AppData%\NuGet\NuGet.Config (Windows user-level)
      • NuGet.Config in your solution / repo (if you have one)
      • Any environment-managed config your company uses
    • After disabling/fixing it, retry “fetch versions” in Studio.
  2. Workaround: install the Suite version explicitly (no “fetch versions” UI needed) Run this in a terminal (same user that runs Studio/Suite):

abp suite install --version 10.2.0
   # or update to an explicit version
   abp suite update --version 10.2.0

Then run:

abp suite
  1. If Suite also uses ABP account/license and you see authentication-related problems Re-login with ABP CLI:
abp logout
   abp login
  1. After you can manage Suite versions again, go back to your original issue and ensure:
    • Suite version == Volo.Abp.Commercial.SuiteTemplates version
    • delete all bin/obj and rebuild the solution

(Verified)

  • https://abp.io/docs/10.2/suite/how-to-install
  • https://abp.io/support/questions/3757

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 error is thrown by ABP Suite when it can’t find/read the embedded template resources from the same version of Volo.Abp.Commercial.SuiteTemplates that matches your installed ABP Suite version, or when your solution output still contains old assemblies (common after upgrading from 9.x to 10.x).

Do the following in order (this fully fixes the “template missing …ApplicationMapperlyMapper_Usings.txt” class of errors):

  1. Make ABP Suite version match your solution (10.2.x)

    • If you are running Suite from ABP Studio, use the “change version”/version matching UI so Suite matches the solution’s ABP version.
    • If you run Suite standalone, update/downgrade Suite so it is exactly compatible with ABP 10.2.0.
  2. Ensure Volo.Abp.Commercial.SuiteTemplates version matches the Suite version

    • In your solution, locate all references to Volo.Abp.Commercial.SuiteTemplates and make sure the version is exactly the same as the ABP Suite version you’re running (not just “10.x”, but the exact patch line).
    • Restore packages.
  3. Hard clean the solution outputs (removes stale 9.x assemblies)

    • Close Visual Studio/Rider (important).
    • Delete all bin and obj folders under the entire solution (all microservices and shared projects).
    • Reopen the solution.
  4. Build the solution (Suite requires a recent build)

    • Build the whole solution (or at least the target service you generate code for).
    • Then restart ABP Suite and try generation again.
  5. If you migrated to Mapperly: keep Suite-managed mapper files “clean”

    • Since your error references ApplicationMapperly..., you are on the Mapperly path. Keep the conventional, Suite-managed files in ObjectMapping (like *ApplicationMappers.cs) reserved for Suite updates.
    • Put your manual mappings in separate files with different naming so Suite doesn’t pick the wrong file.

This is why having an ObjectMapping/SettingServiceApplicationMappers file is fine, but if there are extra/misnamed files or stale builds, Suite may not resolve the expected template-to-file conventions correctly.

Links (verified):

  • https://abp.io/docs/10.2/suite/editing-templates
  • https://abp.io/docs/10.2/studio/working-with-suite
  • https://abp.io/docs/10.2/release-info/migration-guides/AutoMapper-To-Mapperly

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.

  • Recommended approach (tenant-based validation with single LDAP):

    1. Keep LDAP as the credential validator (username/password against LDAP).
    2. After LDAP says “password is valid”, query LDAP (or your LDAP-derived mapping service) to get the user’s Unit/Org.
    3. Compare that Unit/Org to the current tenant context (the tenant resolved from __tenant, subdomain, etc.).
    4. If they don’t match, reject the sign-in (do not issue cookies/tokens).

    In ABP, the cleanest place to do this for the interactive OpenIddict login is to override the login page model and inject your LDAP check there, right before calling the base sign-in logic.

  • Where to intervene in the OpenIddict login flow:

    • For the interactive login page (/Account/Login), intervene in the Account login page post handler (i.e., in a custom LoginModel override) before the framework completes the sign-in and OpenIddict proceeds to generate the authorization response.
    • If you also need to cover custom authorize behavior, ABP support confirms you can alternatively override the default OpenIddict authorize endpoint by overriding AuthorizeController in your project, and you can check authentication state with:
var result = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme);
(This is useful when you need to enforce extra rules during `/connect/authorize`.)  
Source: ABP support answer for overriding authorize flow. (link below)
  • How to ensure host (super admin) login remains exempt:

    • Make the restriction conditional on tenant context:
      • If CurrentTenant.Id == null (host side), skip the LDAP Unit/Org-to-tenant validation entirely.
      • Only enforce the Unit/Org check when CurrentTenant.Id != null (tenant side).
    • This guarantees host login (including super admin) is unaffected.
  • Minimal implementation outline (custom login page model):

using System.Threading.Tasks;
  using Microsoft.AspNetCore.Mvc;
  using Microsoft.Extensions.Options;
  using Volo.Abp.Account.Web;
  using Volo.Abp.Account.Web.Pages.Account;
  using Volo.Abp.DependencyInjection;
  using Volo.Abp.MultiTenancy;

  public class LdapTenantRestrictedLoginModel : LoginModel, ITransientDependency
  {
      private readonly ICurrentTenant _currentTenant;
      private readonly ILdapUnitResolver _ldapUnitResolver; // your service
      private readonly ITenantUnitMapping _tenantUnitMapping; // your service

      public LdapTenantRestrictedLoginModel(
          IAuthenticationSchemeProvider schemeProvider,
          IOptions<AbpAccountOptions> accountOptions,
          IOptions<Microsoft.AspNetCore.Identity.IdentityOptions> identityOptions,
          IdentityDynamicClaimsPrincipalContributorCache contributorCache,
          ICurrentTenant currentTenant,
          ILdapUnitResolver ldapUnitResolver,
          ITenantUnitMapping tenantUnitMapping)
          : base(schemeProvider, accountOptions, identityOptions, contributorCache)
      {
          _currentTenant = currentTenant;
          _ldapUnitResolver = ldapUnitResolver;
          _tenantUnitMapping = tenantUnitMapping;
      }

      public override async Task<IActionResult> OnPostAsync(string action)
      {
          // Host login is exempt
          if (_currentTenant.Id != null)
          {
              // 1) Validate credentials + resolve unit from LDAP (implementation is yours)
              var unit = await _ldapUnitResolver.ResolveUnitAsync(
                  LoginInput.UserNameOrEmailAddress,
                  LoginInput.Password
              );

              // 2) Compare unit to current tenant
              var expectedUnit = await _tenantUnitMapping.GetUnitForTenantAsync(_currentTenant.Id.Value);

              if (unit != expectedUnit)
              {
                  Alerts.Danger("You are not allowed to sign in to this tenant.");
                  return Page();
              }
          }

          // Continue with the normal ABP login flow (cookies/OpenIddict)
          return await base.OnPostAsync(action);
      }
  }

Register it by creating a page override in your host project under Pages/Account/Login.cshtml.cs (same razor page route) so ABP uses your model for /Account/Login.


  • https://abp.io/docs/latest/modules/openiddict
  • https://abp.io/support/questions/10001
  • https://abp.io/community/articles/e59qfi9n

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 apply any SQLite PRAGMA tuning by default. When you switch an ABP solution to SQLite, ABP essentially expects you to configure EF Core with UseSqlite(...) (connection string / options) and it doesn’t automatically set WAL, busy_timeout, cache_size, etc.
  • To ensure those PRAGMAs are always applied, configure them yourself at the ADO.NET/EF Core level.

Option 1 (recommended): Put PRAGMAs into the SQLite connection string

Microsoft.Data.Sqlite supports many PRAGMAs via connection string keywords. In an ABP app, this means you can set them in appsettings.json:

{
  "ConnectionStrings": {
    "Default": "Data Source=app.db;Cache=Shared;Pooling=True;Foreign Keys=True;Journal Mode=WAL;Synchronous=Normal;Busy Timeout=5000"
  }
}

Then ABP/EF Core will use it as usual (your existing UseSqlite(configuration.GetConnectionString("Default"))).

Notes:

  • This cleanly applies settings for every connection created by EF Core.
  • Not every PRAGMA you listed is available as a connection string keyword (depends on provider support).

Option 2: Execute PRAGMAs when a DbConnection is opened (covers all PRAGMAs)

If you need PRAGMAs like mmap_size, cache_size, journal_size_limit reliably, run raw SQL PRAGMA statements right after the connection opens. The simplest ABP-friendly place is your DbContext:

using Microsoft.EntityFrameworkCore;

public class MyDbContext : AbpDbContext<MyDbContext>
{
    public MyDbContext(DbContextOptions<MyDbContext> options)
        : base(options)
    {
        // Ensure PRAGMAs are set when DbContext is created
        Database.OpenConnection();

        // Apply PRAGMAs
        Database.ExecuteSqlRaw("PRAGMA journal_mode = WAL;");
        Database.ExecuteSqlRaw("PRAGMA synchronous = NORMAL;");
        Database.ExecuteSqlRaw("PRAGMA mmap_size = 134217728;");
        Database.ExecuteSqlRaw("PRAGMA cache_size = 2000;");
        Database.ExecuteSqlRaw("PRAGMA busy_timeout = 5000;");
        Database.ExecuteSqlRaw("PRAGMA foreign_keys = ON;");
        Database.ExecuteSqlRaw("PRAGMA journal_size_limit = 67108864;");
    }
}

Important:

  • PRAGMA journal_mode=WAL and similar settings are connection-level / database-level behaviors; ensure they’re applied consistently for all app instances.
  • If you use migrations/DbMigrator, make sure the migrator app also applies the same PRAGMAs (it has its own startup/DbContext creation).

Option 3: Interceptor (centralized, applied per-connection)

You can implement an EF Core DbConnectionInterceptor that runs PRAGMAs on ConnectionOpened and register it in your module where you configure AbpDbContextOptions. This avoids putting it into the DbContext constructor and makes it easier to reuse across multiple DbContexts.


  • https://abp.io/docs/10.1/framework/data/entity-framework-core/sqlite

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.

  • /api/abp/application-configuration is expected to be called right after login (Angular/MVC UIs use it to bootstrap current user, settings, features, permissions, etc.). When this endpoint is slow, it’s almost always because one (or more) of the contributors behind it is doing expensive work (typically: permission/policy resolution, settings retrieval, or any custom IApplicationConfigurationContributor you added), or because the app is doing “first request” warm-up work (cold start, DB connection pool warmup, etc.).

1) Identify what’s slow (server-side) with minimal changes

Enable detailed timing on the server to see where time is spent for that single request:

  1. Turn on ABP/Microsoft logs at least for the configuration pipeline categories in your AuthServer/Host:

    • Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations
    • Volo.Abp.Authorization
    • Volo.Abp.Settings
    • Volo.Abp.FeatureManagement (if enabled)
    • Microsoft.EntityFrameworkCore.Database.Command (to catch slow SQL)
  2. Reproduce login once and inspect the logs for:

    • slow SQL queries
    • repeated authorization checks
    • remote calls (in microservice/gateway scenarios)
    • any custom contributor executing heavy code

This step is the fastest way to get a definitive root cause because the endpoint itself is just an “aggregator”.

2) The most common causes + fixes

A) Granted policies (permissions) computation is slow application-configuration returns auth.grantedPolicies. If you have:

  • a lot of permissions,
  • many roles/claims,
  • custom permission value providers hitting DB, this part can dominate response time.

Fix approaches:

  • Reduce expensive DB work in custom PermissionValueProvider implementations.
  • Ensure related tables (user-role, role-permission, etc.) are properly indexed.
  • Avoid per-permission database queries (N+1) in any customization.

B) Settings retrieval is slow (especially if stored in DB) If you heavily use Setting Management and many modules/settings are enabled, the endpoint reads a large settings set.

Fix approaches:

  • Ensure distributed cache is configured and healthy (e.g., Redis in production).
  • Verify there are no slow DB queries from setting stores.

C) Cold start / first request after deployment If the first login after an idle period is slow but subsequent ones are fast, it’s typically:

  • app cold start (JIT, DI graph creation),
  • first DB connection establishment,
  • first-time cache population.

Fix approaches:

  • Deploy with Release and production optimizations.
  • Keep the app “warm” (health checks / periodic pings).
  • Ensure DB connection pooling is correctly configured.

D) Reverse proxy / gateway adds latency In tiered or microservice setups, application-configuration may be proxied through gateways. This can add:

  • extra hop latency,
  • token validation overhead,
  • DNS/TLS overhead.

Fix approaches:

  • Compare timing when calling the underlying service directly vs via gateway.
  • Enable HTTP/2 between gateway and services if possible.
  • Ensure token validation metadata is cached and not refetched frequently.

3) What you can do immediately (safe, ABP-aligned)

  1. Confirm whether it’s always ~4s or mostly the first request:
    • If only first request is slow, focus on cold-start and caching.
  2. Check whether auth.grantedPolicies is huge:
    • In the response JSON, if auth.grantedPolicies contains many entries, permission resolution is a prime suspect.
  3. Ensure caching (especially distributed cache) is enabled/working in production.

4) Verified reference for this endpoint

  • https://abp.io/docs/latest/framework/api-development/standard-apis/configuration

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.

  • You can reuse your Blazor UI code only if it’s real Blazor components (Razor .razor files) and not tied to WebAssembly hosting specifics.
    In practice, this means you can move/share pages/components into a shared Razor Class Library (RCL) and then use them from a .NET MAUI Blazor Hybrid app.

  • ABP does not provide an “official template/feature” that automatically turns an ABP Blazor Web App UI into a MAUI Blazor Hybrid app without work. You’ll need to create a MAUI client and integrate it (auth + API consumption), then reference your shared UI components.

  • Important constraint: If your “Blazor Web App” is ABP’s Blazor WebAssembly UI (with ABP’s WASM theme/components), it usually won’t be a drop-in reuse in MAUI. You typically can still reuse pure Razor components/pages, but you may need to adapt:

    • authentication flow (MAUI uses device/browser-based OIDC),
    • navigation/root layout,
    • any browser-specific JS interop,
    • any ABP WASM-specific UI packages/theme usage.

What to do (recommended approach)

  1. Extract reusable UI into a shared project

    • Create a Razor Class Library (RCL), e.g. MyCompany.MyApp.Ui.Shared.
    • Move the pages/components you want to reuse into it.
    • Keep them as “pure” as possible (minimal hosting assumptions).
  2. Create a .NET MAUI Blazor Hybrid app

    • Use MAUI Blazor (Hybrid) so it can render Razor components.
    • Reference the shared RCL from the MAUI app.
  3. Consume your existing ABP backend from MAUI (typical ABP way)

    • Keep ABP backend (HttpApi.Host) as-is.
    • In MAUI, consume your server via ABP HttpApi.Client / client proxies, and implement authentication (OIDC) suitable for mobile.
  4. Implement login/token handling for MAUI

    • Use an OIDC flow appropriate for MAUI, then attach tokens to ABP remote service calls (via ABP’s HTTP client authentication abstractions).

Verified examples you can follow (MAUI client + ABP backend)

These show how to build a MAUI client that consumes an ABP application (auth + client proxies), which is the core missing piece when moving from web UI to MAUI:

  • https://abp.io/community/articles/em7x1s8k
  • https://abp.io/community/articles/e74fmblw
  • https://github.com/abpframework/abp-samples/tree/master/MAUI-OpenId

Also relevant ABP support discussion about MAUI Blazor hybrid direction + sample:

  • https://abp.io/support/questions/3640

  • https://github.com/hikalkan/maui-abp-playing

  • https://community.abp.io/posts/integrating-maui-client-via-using-openid-connect-aqjjwsdf

  • ABP UI options (shows MAUI is a UI option in ABP ecosystem, but not “reuse web UI automatically”):
    https://abp.io/docs/latest/framework/ui/


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.

The ?* you see in the client log is just ABP’s log formatting (it hides the query details). The real proof is on the target service side: earlier you already captured a request arriving as:

/api/abp/application-localization?CultureName=&OnlyDynamics=True&api-version=1.0

So the query parameter exists but ends up empty (CultureName=). That usually happens when the UI app can’t determine the current culture at startup inside the container, so it passes an empty string to the application-localization call.

The most reliable, ABP-consistent fix is: set the default culture explicitly in the UI apps and ensure ABP uses it.

1) Hard-set DefaultThreadCurrentCulture + DefaultThreadCurrentUICulture at startup (PublicWeb + Web)

In Program.cs of TavTechnologies.Treva.Web.Public and TavTechnologies.Treva.Web (before app.InitializeApplicationAsync()), add:

using System.Globalization;

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en");

This guarantees CultureInfo.CurrentUICulture.Name is never empty in the process (container) even before the first HTTP request is fully processed.

2) Also set ABP RequestLocalization default culture (defensive)

Keep/configure RequestLocalizationOptions as well (module ConfigureServices):

context.Services.Configure<RequestLocalizationOptions>(options =>
{
    options.SetDefaultCulture("en");
});

3) Make sure Linux globalization isn’t running in invariant mode

When .NET runs with invariant globalization, cultures can behave unexpectedly. In your PublicWeb/Web container, ensure this env var is not true:

  • DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false

(If it’s missing, that’s fine; just don’t set it to true.)

Why this fixes your specific symptom

ABP’s application-localization endpoint requires cultureName (validated by ABP and documented). Your backend logs showed CultureName=. The only way that happens is: the caller (MVC UI) is constructing the request with an empty culture value. For containerized deployments, explicitly setting DefaultThreadCurrentUICulture is the most deterministic way to prevent an empty culture during early startup.

Reference

  • https://abp.io/docs/10.2/framework/api-development/standard-apis/localization

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 log still shows the MVC UI is calling:

GET http://treva-publicgateway/api/abp/application-localization?*

So the UI-side override you added is not being used at all (otherwise you would see cultureName=... on the outgoing request).

The most definitive way to fix this without relying on the UI client pipeline is to make the gateway always supply a default cultureName when it proxies /api/abp/application-localization.

Solution

In PublicWebGateway (YARP-based gateway), add a transform for the /api/abp/application-localization route so that if cultureName is missing, it is added.

Example (in the gateway module ConfigureServices):

using Microsoft.Extensions.DependencyInjection;
using System;

public override void ConfigureServices(ServiceConfigurationContext context)
{
    context.Services.AddReverseProxy()
        .AddTransforms(builderContext =>
        {
            // Apply only for the app-localization endpoint
            if (builderContext.Route?.Match?.Path != null &&
                builderContext.Route.Match.Path.Contains("/api/abp/application-localization", StringComparison.OrdinalIgnoreCase))
            {
                builderContext.AddRequestTransform(transformContext =>
                {
                    var query = transformContext.HttpContext.Request.Query;

                    // If cultureName is missing or empty, force a default
                    if (!query.ContainsKey("cultureName") || string.IsNullOrWhiteSpace(query["cultureName"]))
                    {
                        var original = transformContext.ProxyRequest.RequestUri;

                        // Append required query string parameters
                        var separator = string.IsNullOrEmpty(original!.Query) ? "?" : "&";
                        var newUri = new Uri(original.ToString() + $"{separator}cultureName=en&onlyDynamics=true");

                        transformContext.ProxyRequest.RequestUri = newUri;
                    }

                    return ValueTask.CompletedTask;
                });
            }
        });
}

This guarantees the downstream service receives a valid request like: /api/abp/application-localization?cultureName=en&onlyDynamics=true and prevents the startup crash.

Why this is the correct next step

  • Your logs prove the request reaches the gateway without cultureName.
  • Even after UI-side changes, the outgoing request is still ?*, meaning the UI override isn’t actually active (wrong service replaced, wrong project/module, or not loaded).
  • The gateway transform is the last “central” place where you can unconditionally enforce the required parameter for all callers.

Reference (requirement)

cultureName is required for /api/abp/application-localization:

  • https://abp.io/docs/10.2/framework/api-development/standard-apis/localization

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.

The key detail in your new log is this:

GET http://treva-publicgateway/api/abp/application-localization?*

That means the MVC UI is calling the endpoint without cultureName at all (not even empty). ABP’s /api/abp/application-localization endpoint requires cultureName, so the gateway correctly returns 400, and the UI crashes while building request localization options.

Since you already tried proxy/header/default culture ideas and nothing changed, the most reliable fix is to force the MVC UI to always include cultureName when requesting application-localization by overriding the client that makes that call.

Solution (override the MVC cached application configuration client)

In both TavTechnologies.Treva.Web and TavTechnologies.Treva.Web.Public:

  1. Create a custom implementation:
using System.Globalization;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.Client;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.DependencyInjection;

public class FixedMvcCachedApplicationConfigurationClient : MvcCachedApplicationConfigurationClient, ITransientDependency
{
    private readonly IAbpApplicationLocalizationAppService _localizationAppService;

    public FixedMvcCachedApplicationConfigurationClient(
        IAbpApplicationConfigurationAppService applicationConfigurationAppService,
        IAbpApplicationLocalizationAppService localizationAppService)
        : base(applicationConfigurationAppService, localizationAppService)
    {
        _localizationAppService = localizationAppService;
    }

    protected override Task<ApplicationLocalizationDto> GetLocalizationAsync()
    {
        // Ensure cultureName is never missing
        var cultureName = CultureInfo.CurrentUICulture?.Name;
        if (string.IsNullOrWhiteSpace(cultureName))
        {
            cultureName = "en";
        }

        return _localizationAppService.GetAsync(new ApplicationLocalizationRequestDto
        {
            CultureName = cultureName,
            OnlyDynamics = true
        });
    }
}
  1. Replace the default service registration in your web module:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp.AspNetCore.Mvc.Client;

public override void ConfigureServices(ServiceConfigurationContext context)
{
    context.Services.Replace(ServiceDescriptor.Transient<
        MvcCachedApplicationConfigurationClient,
        FixedMvcCachedApplicationConfigurationClient>());
}

This guarantees the call becomes:

/api/abp/application-localization?cultureName=en...

and avoids the startup crash even if something in your environment is preventing ABP from determining culture normally.

Why this works

Your logs prove the request is being made without cultureName. The ABP endpoint requires it, and returns 400 when it’s missing. By forcing the client to always send a non-empty culture, you bypass the failing path and your UI can start.

Verified reference

  • /api/abp/application-localization requires cultureName: https://abp.io/docs/10.2/framework/api-development/standard-apis/localization

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 361 to 370 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.