What’s happening:
End-to-end steps to call protected APIs from your Next.js app using the SSO token:
${process.env.NEXT_PUBLIC_API_URL}/api/identity/my-profile, {
headers: {
Authorization: Bearer ${accessToken},
'Accept-Language': 'en', // optional
'Abp-TenantId': tenantId ?? '' // if you use multi-tenancy and need to target a tenant
}
});
if (res.status === 401) {
// handle re-auth or token refresh
}Minimal code example (server-side Next.js API route proxying to ABP API):
// /pages/api/me.ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const accessToken = req.headers['authorization']?.toString().replace(/^Bearer\s+/i, '');
if (!accessToken) {
return res.status(401).json({ error: 'No access token' });
}
const apiUrl = process.env.NEXT_PUBLIC_API_URL; // e.g. https://localhost:44350
const r = await fetch(`${apiUrl}/api/identity/my-profile`, {
headers: { Authorization: `Bearer ${accessToken}` }
});
if (!r.ok) {
return res.status(r.status).send(await r.text());
}
return res.status(200).json(await r.json());
}
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 to make it work reliably in MVC Razor Pages:
Ensure static JS proxies are enabled and generated
Use the new global namespace when calling APIs
Verify the actual namespace at runtime
Common pitfalls to check
Minimal working example // 1) After correct proxy generation and layout setup: // window.myCompany.myApp.default.bangGiaVeNgays.bangGiaVeNgays.create({ ... }) window.myCompany.myApp.default.bangGiaVeNgays.bangGiaVeNgays .getList({ skipCount: 0, maxResultCount: 10 }) .then(result => console.log(result)) .catch(err => console.error(err));
Does the latest ABP still support calling services like before?
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 call bypasses ABP’s interception pipeline. Checklist:
Auditing middleware and options
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
app.UseAuditing();
}
Configure<AbpAuditingOptions>(options =>
{
options.IsEnabled = true;
// optional:
// options.IsEnabledForGetRequests = true;
// options.AlwaysLogOnException = true;
});
Ensure you didn’t use [DisableAuditing] on the service or method.
Entity change logs require UoW + change tracking selection Create/Update “action logs” should appear even without entity changes, but if you expect EntityChanges, ensure:
Configure<AbpAuditingOptions>(options =>
{
options.EntityHistorySelectors.AddAllEntities(); // or add your entity types explicitly
});
Your DbContext is not being saved outside ABP’s UoW unexpectedly.
Verify the proxy is actually used in Blazor Temporarily assert interception by forcing auditing:
[Audited]
public class SeasonAppService : CrudAppService<Season, SeasonDto, Guid, PagedAndSortedResultRequestDto, CreateSeasonDto, UpdateSeasonDto>,
ISeasonAppService
{
public override async Task<SeasonDto> CreateAsync(CreateSeasonDto input) { ... }
public override async Task<SeasonDto> UpdateAsync(Guid id, UpdateSeasonDto input) { ... }
}
If this still doesn’t create an audit log, interception is likely bypassed.
public override async Task<SeasonDto> CreateAsync(CreateSeasonDto input)
{
return await base.CreateAsync(input);
}
public override async Task<SeasonDto> UpdateAsync(Guid id, UpdateSeasonDto input)
{
return await base.UpdateAsync(id, input);
}
Do not seal the class or methods.
[Inject] protected ISeasonAppService SeasonAppService { get; set; } = default!;
Do not cast to the concrete type or call non-virtual helpers on the class.
Custom IAuditingStore If you replaced IAuditingStore, ensure SaveAsync is called and not filtering out Create/Update. Log inside your store to verify it’s invoked for Create/Update paths.
Quick diagnostic
If after all checks Delete is audited but Create/Update are not:
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.
Fixes (apply all that match your case):
public partial class MyPage : ComponentBase
{
// Good: inject the interface that inherits IApplicationService
[Inject] private IMyEntityAppService MyEntityAppService { get; set; } = default!;
private async Task SaveAsync(CreateMyEntityDto input)
{
await MyEntityAppService.CreateAsync(input); // audited by proxy
}
}
Ensure your interface implements IApplicationService:
public interface IMyEntityAppService : IApplicationService
{
Task<MyEntityDto> CreateAsync(CreateMyEntityDto input);
Task<MyEntityDto> UpdateAsync(Guid id, UpdateMyEntityDto input);
Task DeleteAsync(Guid id);
Task<PagedResultDto<MyEntityDto>> GetListAsync(PagedAndSortedResultRequestDto input);
}
Do not inject the concrete class into the Blazor page/component. If you must access implementation-only members, expose them via the interface or use a domain service behind the app service.
Ensure auditing is enabled for app service methods:
Configure<AbpAuditingOptions>(options =>
{
options.IsEnabled = true;
options.IsEnabledForGetRequests = true; // optional
options.AlwaysLogOnException = true;
// Track entity changes if needed:
options.EntityHistorySelectors.AddAllEntities();
});
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
app.UseAuditing();
}
Ensure the UoW is active and SaveChanges happens inside the same call so EntityChange logs are produced. Using standard repositories inside application services with ABP’s UnitOfWork ensures that. Avoid calling repositories outside of an app-service/UoW boundary.
Confirm you are not suppressing interceptors:
If you have replaced IAuditingStore or use a remote store, ensure SaveAsync is called; check logs of your auditing store.
Quick verification
[Audited]
public class MyEntityAppService : ApplicationService, IMyEntityAppService
{
public virtual async Task<MyEntityDto> CreateAsync(CreateMyEntityDto input) { ... }
}
If you instead prefer calling over HTTP even from Blazor Server, you can inject the dynamic C# client (HttpApi.Client) for the same interface. That path always goes through the server pipeline and auditing.
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) Use the official Version Mapping inside ABP Studio (recommended)
B) Use the supported “switch version” script pattern but only with existing packages
param (
[string]$version = "1.4.2",
[string]$channel = "release"
)
$installdir = "$env:LOCALAPPDATA\abp-studio\"
$file = "abp-studio-$version-$channel-full.nupkg"
$url = "https://abp.io/api/abp-studio/r/download/windows/$file" # note the '/r/download/windows' path used by the official updater logs
$pkgDir = "$installdir\packages"
$outputPath = Join-Path $pkgDir $file
Write-Host "Installing to $installdir"
if (-not (Test-Path $pkgDir)) { New-Item -ItemType Directory -Path $pkgDir -Force | Out-Null }
try {
$resp = Invoke-WebRequest -Uri $url -Method Head -UseBasicParsing -ErrorAction Stop
} catch {
Write-Error "Package not found on feed: $url. Please choose another Studio version present on the feed."
exit 1
}
if (-not (Test-Path $outputPath)) {
Write-Host "Downloading $url to $outputPath"
Invoke-WebRequest -Uri $url -OutFile $outputPath -UseBasicParsing
} else {
Write-Host "File already present: $outputPath"
}
$updateExe = Join-Path $installdir "Update.exe"
Write-Host "Applying package..."
& $updateExe apply --package $outputPath
Write-Host "Done."
C) Use ABP Studio CLI aligned to 9.3.6
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.
ABP Studio 1.4.2 is the correct Studio version to generate solutions with ABP 9.3.6 (per the official mapping).
The 404 happens because the package name you’re trying to download is wrong. Studio 1.4.2 is a stable release, not beta. Use the stable “release” channel package name:
Quick fix for the script:
param (
[string]$version = "1.4.2",
[string]$channel = "release"
)
$installdir = "$env:LOCALAPPDATA\abp-studio\"
Write-Host "Installing to $installdir"
$file = "abp-studio-$version-$channel-full.nupkg"
$url = "https://abp.io/api/abp-studio/download/r/windows/$file"
$outputPath = "$installdir\packages\$file"
if (-not (Test-Path $installdir)) { New-Item -ItemType Directory -Path $installdir -Force | Out-Null }
if (-not (Test-Path "$installdir\packages")) { New-Item -ItemType Directory -Path "$installdir\packages" -Force | Out-Null }
if (Test-Path $outputPath) {
Write-Host "File $file already exists. Skipping download."
} else {
Write-Host "Downloading $url to $outputPath"
Invoke-WebRequest -Uri $url -OutFile $outputPath
}
$updateExe = "$installdir\Update.exe"
Write-Host "Running $updateExe apply --package $outputPath"
& $updateExe apply --package $outputPath
Write-Host "ABP Studio version $version ($channel) installed successfully."
After installation:
Alternative (without Studio UI): You can also use ABP Studio CLI of that version to create the project in a CI/terminal environment. Ensure the Studio CLI version aligns with 1.4.2 (bundled with Studio), then run abp new with your template options. However, using the Studio UI 1.4.2 is simpler since it already binds to 9.3.6.
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.
context.Menu.AddItem(
new ApplicationMenuItem(
"MyHome",
"Home",
url: "/",
icon: "fa fa-home",
order: 0
)
);
- If you customize the built-in Home item, ensure its Url is “/” (not null/empty).
var url = string.IsNullOrWhiteSpace(MenuItem.MenuItem.Url)
? "/"
: MenuItem.MenuItem.Url.TrimStart('/', '~');
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.
Verify and fix with the checklist below.
A) Ensure dynamic JS proxy is enabled
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(KSVRApplicationModule).Assembly);
});
Configure<AbpAspNetCoreMvcClientProxyOptions>(options =>
{
// default is dynamic proxies ON; ensure not disabled globally
// options.DisableAbpDynamicProxyScript = false; // only if you had set it true somewhere
});
B) Load the dynamic proxy script on the page
<script src="~/Abp/ApplicationConfigurationScript"></script>
<script src="~/Abp/ServiceProxyScript"></script>
<script src="~/libs/jquery/jquery.js"></script>
<script src="~/libs/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- ... other abp libs -->
<script src="~/Pages/BangGiaVeNgays/index.js"></script>
C) Confirm correct Root Namespace in JS
var bangGiaVeNgayService = window.webCMS.KSVR.services.bangGiaVeNgays.bangGiaVeNgays;
This will only work if:
D) Ensure your AppService is exposed to HTTP (so proxy can be generated)
[RemoteService(true)]
public class BangGiaVeNgayAppService : ApplicationService, IBangGiaVeNgayAppService
{
// ...
}
E) If it’s a tiered setup (Auth Server separated)
"RemoteServices": {
"Default": {
"BaseUrl": "https://localhost:443xx" // your HttpApi.Host
}
}
"RemoteServices": {
"Default": {
"BaseUrl": "https://localhost:443xx"
},
"KSVR": {
"BaseUrl": "https://localhost:443xx"
}
}
F) Confirm the final JS object path
G) Common pitfalls to fix
Once the above are corrected, the line like below should work without error:
var l = abp.localization.getResource('KSVR');
var bangGiaVeNgayService = window.WebCMS.KSVR.services.bangGiaVeNgays.bangGiaVeNgays;
bangGiaVeNgayService.getList({ filter: '...' }).then(res => {
// ...
});
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.
Root cause
Recommended fix (create tables for every EF Core module DbContext used during tests)
Example (extend your existing CreateDatabaseAndGetConnection and service configuration):
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
using Volo.Abp.LanguageManagement.EntityFrameworkCore;
[DependsOn(
typeof(AdministrationServiceEntityFrameworkCoreModule),
typeof(AbpEntityFrameworkCoreSqliteModule),
typeof(AbpLanguageManagementEntityFrameworkCoreModule) // add this
)]
public class AdministrationServiceEntityFrameworkCoreTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var sqliteConnection = CreateDatabaseAndGetConnection();
Configure<AbpDbContextOptions>(options =>
{
options.Configure<AdministrationServiceDbContext>(c =>
{
c.DbContextOptions.UseSqlite(sqliteConnection);
});
options.Configure<BlobStoringDbContext>(c =>
{
c.DbContextOptions.UseSqlite(sqliteConnection);
});
// configure LanguageManagementDbContext to use the same connection
options.Configure<LanguageManagementDbContext>(c =>
{
c.DbContextOptions.UseSqlite(sqliteConnection);
});
});
}
private static SqliteConnection CreateDatabaseAndGetConnection()
{
var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
// AdministrationService
new AdministrationServiceDbContext(
new DbContextOptionsBuilder<AdministrationServiceDbContext>().UseSqlite(connection).Options
).GetService<IRelationalDatabaseCreator>().CreateTables();
// BlobStoring
new BlobStoringDbContext(
new DbContextOptionsBuilder<BlobStoringDbContext>().UseSqlite(connection).Options
).GetService<IRelationalDatabaseCreator>().CreateTables();
// LanguageManagement: creates AbpLanguages, AbpLanguageTexts, etc.
new LanguageManagementDbContext(
new DbContextOptionsBuilder<LanguageManagementDbContext>().UseSqlite(connection).Options
).GetService<IRelationalDatabaseCreator>().CreateTables();
return connection;
}
}
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) Confirm tenant resolution and middleware order
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseMultiTenancy();
app.UseAuthorization();
app.Use(async (ctx, next) =>
{
var currentTenant = ctx.RequestServices.GetRequiredService<ICurrentTenant>();
var logger = ctx.RequestServices.GetRequiredService<ILogger<YourModule>>();
logger.LogInformation("CurrentTenant: Id={Id}, Name={Name}", currentTenant.Id, currentTenant.Name);
await next();
});
If you consistently see Id = null for authenticated tenant requests, tenant resolution is failing.
B) Validate tenant resolvers (domain/header/claim)
C) Prove the connection string resolver actually returns the tenant DB
public class ConnDebugAppService : ApplicationService
{
private readonly IConnectionStringResolver _resolver;
public ConnDebugAppService(IConnectionStringResolver resolver) => _resolver = resolver;
public async Task<string> GetDefaultConnAsync()
{
return await _resolver.ResolveAsync(ConnectionStrings.DefaultConnectionStringName);
}
}
D) Ensure DbContexts are not pinning the Host connection
Configure<AbpDbContextOptions>(options =>
{
options.Configure<MyMainDbContext>(opt => opt.UseSqlServer());
options.Configure<MyTenantDbContext>(opt => opt.UseSqlServer());
// or UseMySQL/UseNpgsql per context if you have multiple DBMS
});
E) Entities, repositories, and background processes
using (CurrentTenant.Change(tenantId))
{
// repositories/services here
}
F) SaaS connection strings and ABP 9+/10+ validation
[Dependency(ReplaceServices = true)]
public class EncryptedConnectionStringChecker
: SqlServerConnectionStringChecker, IConnectionStringChecker, ITransientDependency
{
private readonly IStringEncryptionService _enc;
public EncryptedConnectionStringChecker(IStringEncryptionService enc) => _enc = enc;
public override async Task<AbpConnectionStringCheckResult> CheckAsync(string connectionString)
{
var plain = _enc.Decrypt(connectionString);
return await base.CheckAsync(plain);
}
}
If the framework thinks the string is invalid, it can silently fall back to Host DB behavior afterward.
G) Turn on DB/EF logging to see which connection is used
Configure<AbpEfCoreOptions>(options =>
{
options.Configure(ctx =>
{
ctx.DbContextOptions
.EnableDetailedErrors()
.EnableSensitiveDataLogging();
});
});
H) Cross-cutting checks that commonly cause “always Host DB”
I) Quick “prove it” steps
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.