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
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 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