Hi ABP Team
We have a scenario where we need to present the audit trail of an entity’s changes on a custom frontend screen. We were reviewing the official ABP documentation but couldn’t find a specific or recommended approach to access this audit data from the backend in a way that suits our needs.
We found a third party forum post mentioning the use of EfCoreAuditLogRepository
for a similar use case. Based on that hint, we installed the Volo.Abp.AuditLogging.EntityFrameworkCore
package in the Application layer of our ABP module and explicitly instantiated it in the ProcurementApplicationModule
class. With this setup, we were able to retrieve the entity changes as needed for our frontend.
We would like to clarify two things:
1. Is there any official or recommended approach by ABP to access an entity’s audit logs according to our use case? If so, we would really appreciate it if you could share a link to the official documentation or any related resources.
2. If ABP does not have an official or recommended approach for this scenario, would our current implementation (using EfCoreAuditLogRepository
in the Application layer) cause any issues now or in the future, or is it acceptable to continue working this way?
For your reference, here is a simplified version of our code in the ApplicationModule
and AppService
classes:
// ApplicationModule
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
using Volo.Abp.Application;
using Volo.Abp.BackgroundWorkers.Hangfire;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.BackgroundWorkers;
using Aptim.MiApptimWeb.Procurement.Orders;
using Volo.Abp.AuditLogging.EntityFrameworkCore;
namespace Aptim.MiApptimWeb.Procurement;
[DependsOn(
typeof(ProcurementDomainModule),
typeof(ProcurementApplicationContractsModule),
typeof(AbpDddApplicationModule),
typeof(AbpAutoMapperModule)
)]
[DependsOn(typeof(AbpBackgroundWorkersHangfireModule))]
public class ProcurementApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAutoMapperObjectMapper<ProcurementApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<ProcurementApplicationModule>(validate: true);
});
context.Services.AddTransient<EfCoreAuditLogRepository>();
}
public override async Task OnApplicationInitializationAsync(
ApplicationInitializationContext context)
{
await context.AddBackgroundWorkerAsync<MyLogWorker>();
}
}
// AppService
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories;
namespace Aptim.MiApptimWeb.Procurement.Orders;
public class ProcessedOrderAppService(
IRepository<ProcessedOrders, Guid> _repository,
IRepository<StagingPurchaseOrderDetail, Guid> _stagingRepository,
EfCoreAuditLogRepository _auditLogRepository
) : ProcurementAppService, IProcessedOrderAppService
{
public async Task<List<EntityChangeDto>> GetProcessedOrderChangesAsync(Guid entityId)
{
var entityChanges = await _auditLogRepository.GetEntityChangeListAsync(
includeDetails: true,
entityId: entityId.ToString()
);
var result = entityChanges
.OrderBy(ec => ec.ChangeTime)
.Select(ec => new EntityChangeDto
{
ChangeTime = ec.ChangeTime,
ChangeType = ec.ChangeType.ToString(),
PropertyChanges = ec.PropertyChanges
.Select(pc => new PropertyChangeDto
{
PropertyName = pc.PropertyName,
OriginalValue = DeserializeValue(pc.OriginalValue),
NewValue = DeserializeValue(pc.NewValue)
})
.ToList()
})
.ToList();
return result;
}
private string DeserializeValue(string jsonValue)
{
if (jsonValue == null)
{
return null;
}
try
{
return JsonSerializer.Deserialize<string>(jsonValue);
}
catch
{
return jsonValue;
}
}
}
Thank you very much in advance for your support and clarifications.
Best regards, Gabriel
Hi sumeyye.kurtulus,
Thanks again for the follow-up!
Here’s a detailed update on the tsconfig.json
configurations:
tsconfig.json
contains the following path mappings:"paths": {
"@proxy": ["src/app/proxy/index.ts"],
"@proxy/*": ["src/app/proxy/*"],
...
"@modularcrm/products": [
"../modules/modularcrm.products/angular/projects/products/src/public-api.ts"
],
"@modularcrm/products/config": [
"../modules/modularcrm.products/angular/projects/products/config/src/public-api.ts"
],
...
}
tsconfig.json
includes:"paths": {
"@modular-crm/products": [
"projects/products/src/public-api.ts"
],
"@modular-crm/products/config": [
"projects/products/config/src/public-api.ts"
],
"@proxy": ["projects/products/src/lib/proxy/index.ts"],
"@proxy/*": ["projects/products/src/lib/proxy/*"]
}
As you can see, in the module-specific tsconfig.json
, the @proxy
alias points correctly to the generated proxies (projects/products/src/lib/proxy/index.ts
), and the files are correctly placed there.
That’s why I find it a bit strange that the compilation fails with:
../modules/modularcrm.products/angular/projects/products/src/lib/components/products.component.ts:2:32 - error TS2307: Cannot find module '@proxy' or its corresponding type declarations.
Even though the structure and the tsconfig.json
configuration seem correct.
When I manually change the import to a relative path like:
tsCopiarEditarimport { ProductService } from '../proxy';
everything compiles and runs properly.
Is there perhaps an additional step I’m missing to make the @proxy
alias work inside the module's Angular project?
Or should I be configuring something else (maybe in angular.json
or the project references)?
Thank you once again for your continued help—I really appreciate the support while working through this modular setup!
Kind regards, Gabriel
Hi sumeyye.kurtulus,
Thank you for your response. I was finally able to generate the Angular proxies inside the correct module folder by running the command you shared from within the Angular folder of the corresponding module (in this case, /modules/modularcrm.products/angular/
). That resolved the proxy generation issue—thank you!
Now I’ve encountered a different problem. I’m following the ABP guide for the Modular Monolith Application template (ModularCrm), and while the proxy for the
Products
module is being generated correctly, I’m running into an issue with how imports are handled in the IDE.
For example, when I auto-import ProductService
, the IDE generates:
{ ProductService } from '@proxy';
This used to work fine in a previous project based on ABP version 8. However, in this setup, I get the following compile-time error:
../modules/modularcrm.products/angular/projects/products/src/lib/components/products.component.ts:2:32 - error TS2307: Cannot find module '@proxy' or its corresponding type declarations.
If I manually change the import to:
{ ProductService } from '../proxy';
the application compiles and works as expected.
Is this the expected behavior in the new modular structure?
Do I have to manually adjust the import path for each service or DTO I need to use?
Or is there a configuration I might be missing to make the @proxy
alias resolve correctly in this context?
Thanks again for the support!
Kind regards, Gabriel
Hi
I'm working through the Modular Monolith tutorial using the latest ABP version with Angular as the frontend framework. The documentation has been very helpful overall, but I'm running into some issues with Angular integration that I'd appreciate help with. Initially, the Products module wasn’t appearing in the menu. I resolved this by following the solution in [GitHub Issue #20827](https://github.com/abpframework/abp/issues/20827). The main issue now is with Angular proxy generation:
The proxies are being generated in the main application folder (/angular/src/app
) instead of the module-specific folder (/modules/modularcrm.products/angular/src
), which breaks the intended modular architecture. I found a related report in [GitHub Issue #22124](https://github.com/abpframework/abp/issues/22124), where the suggested fix was to tweak generate-proxy
parameters but it wasn't that helpful.
Kind regards, Gabriel
Hi EngincanV,
I'm currently using ABP CLI 0.9.25 (Beta), but I still don't see the "Upgrade to Pro" option. Additionally, when I try running abp upgrade -t app
, I get an error.
Here's the structure of my existing ABP project (version 8.0.5):
Kuppabit.Kissa
> angular
> katze
> kedi
> neko
> paka
> popoki
> aspnet-core
> src
> Kissa.Application
> Kissa.Application.Contracts
...
> modules
> Katze
> src
...
I understand that the latest ABP CLI introduced changes in the project template structure, so I'm wondering: is there a recommended way to upgrade our current project to Pro, or is it necessary to create a new one using the updated CLI?
Thanks in advance for your help.
Best regards, Gabriel
Hi berkansasmaz,
I tried using the "Upgrade to Pro" option in ABP Studio, but I don’t see it available for any of the projects in our solution.
If I'm not mistaken, the screenshots you shared show a project using ABP 9+ being upgraded to Pro. However, our current project is still on version 8.0.5.
Regards, Gabriel
Hello,
We’ve been working on our Modular Monolith Application using ABP Framework Open Source version 8.0.5 for quite some time. In February 2025, we upgraded to the “Team” commercial license and would now like to migrate our existing project to the commercial edition.
However, we haven’t been able to find any official guide or tutorial on how to perform this migration — specifically regarding:
Our setup uses SQL Server and has the Auth Server running as a separate project, in line with the standard ABP separated Auth Server architecture.
Could you please guide us on the recommended steps to follow? Or point us to any available documentation or tutorials that cover this migration path?
Thank you in advance for your support.
Best regards, Gabriel