public class MyDataSeedContributor : IDataSeedContributor, ITransientDependency
{
private readonly ILocalizationTextManager _textManager;
private readonly ICurrentTenant _currentTenant;
public MyDataSeedContributor(ILocalizationTextManager textManager, ICurrentTenant currentTenant)
{
_textManager = textManager;
_currentTenant = currentTenant;
}
public async Task SeedAsync(DataSeedContext context)
{
using (_currentTenant.Change(context?.TenantId))
{
// Portuguese example
await _textManager.SetAsync("LeptonX", "FilterMenu", "pt-BR", "Filtrar menu");
// Add other languages as needed
await _textManager.SetAsync("LeptonX", "FilterMenu", "en", "Filter menu");
}
}
}
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.
Cause
Fix
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAbpRequestLocalization();
app.UseStaticFiles(); // 1: physical wwwroot
app.UseAbpStaticFiles(); // 2: embedded static files from ABP modules
app.UseRouting();
app.UseAuthentication();
app.UseJwtTokenMiddleware();
app.UseAbpClaimsMap();
app.UseAuthorization();
app.UseAuditing();
app.UseConfiguredEndpoints();
}
public class DocsThemeGlobalContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
var style = context.Files;
// styles
style.AddIfNotContains("/libs/@fortawesome/fontawesome-free/css/all.min.css");
var script = context.Files;
// scripts
script.AddIfNotContains("/libs/jquery/jquery.js");
script.AddIfNotContains("/libs/select2/js/select2.full.min.js");
script.AddIfNotContains("/libs/moment/moment.js");
// add any i18n files you actually use:
// script.AddIfNotContains("/libs/select2/js/i18n/en.js");
}
}
That’s Font Awesome not loading. Once /libs/@fortawesome/fontawesome-free/webfonts/... are served correctly (steps 1–3), the icons will render.
Quick checklist for your screenshots
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.
A) Recommended: Use Releases/Tags as versions
B) If you must use Branches as versions
Additional checks
Quick apply to your screenshots
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.
Notes:
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
Yes. ABP supports showing an OTP step after a successful username/password login (Two-Factor Authentication). Users can use Email, SMS, or an Authenticator app. You can allow the user to choose Email or SMS on the OTP screen, or you can restrict to one provider.
Enable 2FA and providers:
How the built-in flow works:
Let the user choose Email or SMS:
public class MyAccountAppService : AccountAppService
{
public override async Task<ListResultDto<NameValue>> GetTwoFactorProvidersAsync(GetTwoFactorProvidersInput input)
{
var result = await base.GetTwoFactorProvidersAsync(input);
// Keep only Email and SMS
result.Items = result.Items.Where(p => p.Name == "Email" || p.Name == "SMS").ToList();
return result;
}
}
Register your derived service in your module to replace the default IAccountAppService.
If you want to force a single provider (e.g., SMS only) and remove the dropdown:
Notes and prerequisites:
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.
Do this checklist and fix:
Generate a proper OpenIddict certificate for production (not the site TLS cert)
Configure ABP OpenIddict to use the PFX in production
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = context.Services.GetConfiguration();
if (!hostingEnvironment.IsDevelopment())
{
PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
{
options.AddDevelopmentEncryptionAndSigningCertificate = false;
});
PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
{
// If your pfx is in content root
serverBuilder.AddProductionEncryptionAndSigningCertificate(
"openiddict.pfx",
"00000000-0000-0000-0000-000000000000"
);
// Set the public HTTPS issuer
serverBuilder.SetIssuer(new Uri(configuration["AuthServer:Authority"]!));
});
}
}
PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
{
var flags = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet;
serverBuilder.AddProductionEncryptionAndSigningCertificate("openiddict.pfx", "00000000-0000-0000-0000-000000000000", flags);
});
Ensure the file is actually present on the server
Keep Authority and metadata HTTPS-only
"AuthServer": {
"Authority": "https://your-authserver-host",
"RequireHttpsMetadata": true,
"CertificatePassPhrase": "00000000-0000-0000-0000-000000000000"
}
app.Use(async (ctx, next) =>
{
ctx.Request.Scheme = "https";
await next();
});
If you temporarily set RequireHttpsMetadata = false, discovery will emit http URLs and SPAs will reject them; keep it true and fix scheme/forwarding instead.
About the “key rollover” message
IIS-specific tips
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.
What to change
Example const routes: Routes = [ { path: 'identity', loadChildren: () => import('@volo/abp.ng.identity').then(m => m.createRoutes()) }, { path: 'saas', loadChildren: () => import('@volo/abp.ng.saas').then(m => m.createRoutes()) }, { path: 'audit-logging', loadChildren: () => import('@volo/abp.ng.audit-logging').then(m => m.createRoutes()) }, { path: 'language-management', loadChildren: () => import('@volo/abp.ng.language-management').then(m => m.createRoutes()) }, { path: 'text-template-management', loadChildren: () => import('@volo/abp.ng.text-template-management').then(m => m.createRoutes()) }, { path: 'account', loadChildren: () => import('@volo/abp.ng.account').then(m => m.createRoutes()) }, ];
Notes
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 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.
Apply these steps:
Use createRoutes for SAAS routes (even in a module-based app) In your AppRoutingModule (or wherever you define feature routes), load the Saas routes using the package’s route factory. This ensures the Tenants standalone component receives its providers.
Example: import { RouterModule, Routes } from '@angular/router'; import { createRoutes as createSaasRoutes } from '@volo/abp.ng.saas';
const routes: Routes = [ { path: 'saas', loadChildren: () => import('@volo/abp.ng.saas').then(m => createSaasRoutes()), }, // ...other routes ];
@NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], }) export class AppRoutingModule {}
Keep provideSaasConfig() in root providers You already have:
That’s fine. The critical part is that the route uses createSaasRoutes() so the Tenants standalone component runs with the correct Feature providers. If you currently lazy-load a module via SaasConfigModule.forRoot() alone or navigate to the component outside its created routes, the DI context misses feature tokens.
Do not declare or import TenantsComponent manually Don’t import or declare _TenantsComponent (or any SAAS component) directly in your own module. Always navigate through the SAAS routes returned by createSaasRoutes().
Version alignment Ensure all ABP/Commercial Angular packages are on the same exact version range as the ABP CLI template you’re targeting, and Angular is aligned. For ABP 9.3.6:
If you previously used forLazy() Replace any old lazy-load syntax like: loadChildren: () => import('@volo/abp.ng.saas').then(m => m.SaasModule.forLazy({...})) with the new: loadChildren: () => import('@volo/abp.ng.saas').then(m => m.createRoutes({...}))
Last-resort guard If you still see the InjectionToken undefined from a standalone component, it almost always means that page is rendered outside its feature route tree. Double-check that:
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.
What Volo.Abp.Cli is and how it’s used
Why it appears in your vulnerability scan after upgrading to 8.3.4
How to remove or mitigate the vulnerability finding
Important notes
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.