No — you don’t have to download the Basic Theme module as a project just to replace the layout and bundles.
Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic..cshtml files by copying only the files you want to change into your PublicWeb project, preserving the same folder structure (so your files override the embedded ones).AbpBundlingOptions / BundleContributor (no need for theme source code).Only do this if you want to heavily modify the theme as a reusable module (change components deeply, maintain a forked theme, etc.). In that case, ABP explicitly supports copying the Basic Theme source code into your solution.
ABP even provides a CLI command to copy Basic Theme source into your solution:
abp add-source-code Volo.Abp.BasicTheme
(links verified)
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.
AbpBundlingOptions (and optionally using BundleContributor to add/remove/replace files).ABP resolves theme files via the Virtual File System; if you add a file to your app with the same folder structure, your file overrides the theme’s file.
Locate Basic Theme’s original layout/component files (for reference):
modules/basic-theme/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.BasicCopy the file(s) you want to override into your *.Web (PublicWeb) project and keep the same path under the project root, for example:
Themes/Basic/Layouts/Application.cshtmlThemes/Basic/Layouts/Account.cshtmlThemes/Basic/Components/MainNavbar/Default.cshtmlEdit those copied files to match your corporate HTML template.
In your layout, ABP needs its dynamic scripts right after the global script bundle:
<abp-script-bundle name="..." />
<script src="~/Abp/ApplicationConfigurationScript"></script>
<script src="~/Abp/ServiceProxyScript"></script>
These scripts are mentioned in the theming docs and are required for ABP JS-side features that depend on application configuration / proxies.
Basic Theme defines standard bundle names. In your Web module (e.g., YourPublicWebModule), configure AbpBundlingOptions to:
Put your assets under wwwroot (or under wwwroot/libs/...) and then:
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Bundling;
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpBundlingOptions>(options =>
{
options.StyleBundles.Configure(
BasicThemeBundles.Styles.Global,
bundle =>
{
// Add your theme css
bundle.AddFiles("/themes/corporate/css/site.css");
});
options.ScriptBundles.Configure(
BasicThemeBundles.Scripts.Global,
bundle =>
{
// Add your theme js
bundle.AddFiles("/themes/corporate/js/site.js");
});
});
}
Use a BundleContributor and context.Files.ReplaceOne(...) (example shown in the Bootswatch article) to replace Bootstrap with your own CSS (or another framework):
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
public class CorporateStyleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.ReplaceOne(
"/libs/bootstrap/css/bootstrap.css",
"/themes/corporate/css/bootstrap-custom.css"
);
}
}
Register the contributor:
Configure<AbpBundlingOptions>(options =>
{
options.StyleBundles.Configure(
BasicThemeBundles.Styles.Global,
bundle => { bundle.AddContributors(typeof(CorporateStyleContributor)); });
});
ABP support-provided approach (example removes jQuery) is also via BundleContributor:
using System;
using System.Linq;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
public class RemoveJqueryScriptContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
var jquery = context.Files.FirstOrDefault(
x => x.EndsWith("jquery.js", StringComparison.InvariantCultureIgnoreCase));
if (jquery != null)
{
context.Files.Remove(jquery);
}
}
}
And register it on the global scripts bundle.
Use ABP’s resource mapping + abp install-libs workflow (as shown in the Bootswatch article):
node_modules files to wwwroot/libs/... in abp.resourcemapping.jsabp install-libsLinks (validated)
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.
*.Web (keep it for admin/backoffice if you want, or remove it if Solution #2 is only public)*.PublicWeb (your public-facing site with your own theme)YourCompany.PublicWeb (or YourSolutionName.PublicWeb).*.PublicWeb, configure:
*.PublicWeb using ABP’s theming system (start from Basic theme and replace layout + bundles).In ABP terms, Public Website is not a “layer” like Domain/Application; it’s an additional application (a host/UI app) inside the solution.
(verified references)
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.
It should be a tiered UI client (but “UI-only”) in practice:
Tiered (recommended): Create Solution #2 using the tiered application template, so you get a clean separation like:
PublicWeb.HttpApi (controllers that your public MVC pages can call internally if needed, and a place for public endpoints)PublicWeb.Web (the MVC/Razor UI)Domain, Application, EntityFrameworkCore, etc.)Even though Solution #2 won’t host its own AuthServer or HttpApi.Host, using the tiered template aligns best with “this is a separate UI client app that talks to remote AuthServer + remote HttpApi.Host”.
Single-layer: Not recommended for your scenario if you want “full ABP advantages” and long-term maintainability; it’s intended for simpler apps and doesn’t match well with “separate UI solution consuming a remote ABP backend”.
So, for your architecture: Solution #1 remains your existing tiered backend (AuthServer + HttpApi.Host), and Solution #2 should also be created as a tiered ABP MVC solution, but configured to authenticate against Solution #1 AuthServer and call Solution #1 HttpApi.Host as a remote service, while using your corporate theme (Basic theme + custom layout/assets).
Links (verified):
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.
ICurrentUser, permission checks, localization, bundling, etc.) in a first-class way.Below is a complete, end-to-end setup that matches your architecture (Solution #1 = existing tiered backend, Solution #2 = separate public website).
Then you will configure it to point to Solution #1’s endpoints.
In your existing AuthServer (Solution #1), add a new client for the public website, e.g.:
MyCompany_PublicWebhttps://public.mycompany.com/signin-oidc (and dev URLs)https://public.mycompany.com/signout-callback-oidcopenid profile email role + your API scope(s)This is the same pattern as adding any additional UI client to a tiered ABP solution.
Also ensure Solution #1 allows CORS/redirects for the public domain where necessary (mainly affects API calls and OIDC redirect validation).
In Solution #2 (PublicWeb), configure OpenID Connect authority to your AuthServer URL.
Conceptually you will set:
https://auth.mycompany.comMyCompany_PublicWebcodetrue (so you can call HttpApi.Host with access token)(ABP MVC templates already have an OIDC setup style; you will replace the URLs/client settings to point to your existing AuthServer.)
This way, after login, the authenticated principal exists in the MVC app and ABP can populate:
ICurrentUserCurrentTenant (if applicable)In Solution #2, configure a remote service base URL pointing to your existing HttpApi.Host, e.g.:
https://api.mycompany.comThen use ABP’s HTTP API client/proxy approach for consuming endpoints from Solution #1:
*.HttpApi.Client package/project (from Solution #1) into Solution #2 and depending on its module (common ABP pattern for “UI consumes remote service”).This is the same approach described in ABP’s “add microservice UI to an application” guide: add the HttpApi.Client reference and depend on its module from your web module.
Validated reference:
Once Solution #2 is an ABP app and the user authenticates via OIDC:
ICurrentUser)ICurrentUser anywhere in your PublicWeb solution (controllers, razor pages, application services).ABP’s permission system is still the source of truth on the server side (Solution #1). In the Public Website (Solution #2), you typically do:
[Authorize(PermissionName)] (best practice).ABP permission system documentation (validated):
Use ABP MVC theming/bundling and replace the layout & static assets:
wwwroot and register them via ABP bundling/theming.ABP theming doc (validated):
If you need a reference for “overriding the default theme layouts” style behavior, the LeptonX MVC doc explains the MVC theme structure (even if you’re not using it) (validated):
In Solution #1 (existing):
MyCompany_PublicWeb) with correct redirect/logout URLs.In Solution #2 (public website):
If you plan to use ABP’s dynamic JavaScript proxies on a public site, be aware of template differences (some “public web” setups don’t generate proxies by default). If you need dynamic proxies, you may need to enable conventional controllers in that UI project (this is a known pattern in support answers). (If you instead use typed C# HttpApi.Client proxies, you avoid that entirely.)
If you follow the steps above, Solution #2 becomes a “real ABP UI client” of Solution #1, while using your own corporate HTML theme (Basic theme + custom layout/assets), and you’ll be able to use ICurrentUser + ABP authorization/permission infrastructure properly.
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.
ICurrentUser, permission management, ABP’s authorization infrastructure, JS APIs, etc., while authenticating against your AuthServer and calling your HttpApi.Host.Once you do this, ABP will provide ICurrentUser in your UI project (it’s populated from the logged-in principal) and ABP permission checks will work through ABP’s authorization system.
You have two practical options:
AbpAspNetCoreMvcUiBasicThemeModule and replace the UI look by overriding the theme/layout files and including your own CSS/JS bundles.A working example of adding a different MVC theme module (AdminLTE) shows the pattern (add theme module dependency + bring static assets through VFS, etc.). You can apply the same approach with your own theme.
If you are on ABP Commercial and your project has LeptonX, you can override LeptonX layouts by copying layout files into the same virtual path structure (ABP will pick yours). Even if you don’t use LeptonX, the same “layout override” concept applies: put your own layout and set Layout = "...cshtml" in pages when needed.
A verified guide specifically explains overriding LeptonX MVC layouts (same technique: copy layout into your web project with the same folder hierarchy, or point a page to a custom layout path):
ICurrentUser in your MVC controllers/views/services.Sources (verified)
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.
If your ASP.NET Core MVC app is not an ABP application, there is no ABP NuGet package set that will “plug in” ABP features (like ICurrentUser, ABP permission checker, dynamic claims, etc.) into that app the same way an ABP-based UI does. Those are ABP infrastructure pieces that assume an ABP startup/module system and ABP’s application-configuration pipeline.
The supported/straightforward approach for a non-ABP MVC app is:
HttpClient or your own typed clients)./api/abp/application-configuration endpoint or your own “profile” endpoint)./api/abp/application-configuration contains auth-related info for ABP clients), orIf your main goal is to “get full advantage of ABP” from that MVC app, the definitive solution is to convert it to an ABP application (create an ABP MVC UI project and integrate/port your existing UI into it). That’s the only way to use ABP’s built-in concepts (ICurrentUser, ABP permission system integration, JS auth API, etc.) natively.
For client-side permission checks in an ABP MVC/Razor UI, ABP provides a JavaScript Auth API; however, that API assumes ABP UI integration and ABP application-configuration endpoints are available/consumed as ABP expects.
Links (verified):
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.
AbpRemoteCallException + log None of the specified endpoints were reachable happens because the Blazor Server UI is trying to call the AI Management HTTP API, but the remote service base URL for AIManagement is not reachable / not configured correctly in your tiered setup.In your Blazor Server UI project (*.Blazor), set the AI Management remote service base URL in appsettings.json to point to your HttpApi.Host (not the Blazor UI URL):
{
"RemoteServices": {
"Default": {
"BaseUrl": "https://localhost:443xx"
},
"AIManagement": {
"BaseUrl": "https://localhost:443xx"
}
}
}
443xx with the port of your HttpApi.Host.RemoteServices:Default:BaseUrl, still add the AIManagement section to be explicit (and avoid accidental misrouting).Also ensure the same is set in appsettings.Development.json (or whichever environment you run), because environment-specific files override appsettings.json.
Run projects in this order:
*.HttpApi.Host (must be up)*.Blazor (UI)Then verify from your browser:
https://localhost:443xx/api/abp/api-definitionIf this is not reachable, the UI will fail with “endpoints were not reachable”.
In a tiered solution, adding the module to the UI alone is not enough. Ensure AI Management is added to and configured in the HttpApi.Host side (and migrator/db) as ABP Suite/module install expects. Otherwise the UI will call endpoints that don’t exist.
After adding the module, run your database migrator (or apply migrations) so the AI Management tables exist. If tables/config are missing, workspace/provider queries can fail server-side.
AbpRemoteCallException hides the server exception by default on the client. Check logs of HttpApi.Host while opening the Workspaces page; you should see the real exception (DB/migration/config).
Links (verified):
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.
TemplateService.ReadFromTemplateAsync) because it cannot find the embedded resource ApplicationMapperlyMapper_Usings.txt in the Volo.Abp.Commercial.SuiteTemplates assembly it has loaded.If you already cleaned bin/obj and rebuilt and it still happens, then one of these is true:
Volo.Abp.Commercial.SuiteTemplates version than the one Suite expects (often because Central Package Management / Directory.Packages.props / a pinned version somewhere), orDo the following “hard verification” steps (no guesswork):
Volo.Abp.Commercial.SuiteTemplates version resolved by your solutionIn the same project where you generate CRUD (typically the *.HttpApi.Host or the related app project), run:
dotnet list <YourProject>.csproj package --include-transitive | findstr /i "Volo.Abp.Commercial.SuiteTemplates"
Then force it to the exact version you want (10.2.0 or whatever patch you use) by updating the place where you centrally manage versions:
Directory.Packages.props (Central Package Management), orDirectory.Build.props, or<PackageReference ... Version="...">After that:
dotnet restore
ABP Studio supports automatic version matching, but in your environment it previously failed to fetch versions due to the broken Azure DevOps feed. So you must manually ensure only one Suite version is installed and it matches your solution.
Do this:
(Reason: if multiple versions exist, Studio may launch a different installed one even if your solution is 10.2.0.)
Delete bin/obj is not always enough if the wrong SuiteTemplates version is coming from global cache.
Run:
dotnet nuget locals all --clear
Then restore + rebuild again:
dotnet restore
dotnet build
Since the missing template is Mapperly-specific, ensure you didn’t create extra files that match Suite’s conventional mapper file naming.
Make sure you have only one Suite-managed application mapper file for that service, typically:
*ApplicationMappers.csMove your custom mapper code to differently named files (do not use the same *ApplicationMappers.cs suffix).
Volo.Abp.Commercial.SuiteTemplates and must match Suite version)If you apply steps (1) and (2) exactly, this error disappears because Suite will load the SuiteTemplates assembly that actually contains ApplicationMapperlyMapper_Usings.txt.
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.
Volo.Abp.Commercial.SuiteTemplates.Templates.Server.ObjectMapping.ApplicationMapperlyMapper_Usings.txt
That file exists only in the SuiteTemplates package version that matches the Suite version. If Suite is running a different version (or it is loading an older Volo.Abp.Commercial.SuiteTemplates.dll from stale build output), it will throw exactly this “template missing” exception.
Do this fixed sequence (works even when Studio can’t “fetch versions” because of your private NuGet feed):
Force Suite to use the correct version (10.2.x) without the “fetch versions” UI
If you are using the Studio-managed Suite installation, uninstall all installed Suite versions from Studio (or delete the local installed Suite folders) and then install again after you fix NuGet feeds (step 2). The key is: only one Suite version should remain, matching 10.2.x.
Fix the NuGet feed issue so Studio/Suite can actually install/resolve matching packages
https://pkgs.dev.azure.com/.../index.json means your machine has a NuGet source that is unreachable and it breaks NuGet operations.%AppData%\NuGet\NuGet.ConfigNuGet.Config under the repositoryThen clear NuGet caches:
dotnet nuget locals all --clear
Ensure Volo.Abp.Commercial.SuiteTemplates package version exactly matches Suite
Eliminate stale 9.x / older SuiteTemplates assemblies (most common cause after upgrades)
bin and obj folders for the entire solution (every microservice + shared projects).Mapperly-specific note (avoid naming collisions in ObjectMapping)
ApplicationMapperly...), keep Suite-managed conventional mapper files reserved for Suite:
*ApplicationMappers.cs, *BlazorMappers.cs, *WebMappers.csLinks (validated):
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.