Activities of "duyan11110"

Hi,

I don't see any error in the log file. But it's very strange. It works but unstable. Sometime it can publish event, but mostly it does not. Do you have any suggestion for me to check my code?

Hi,

I setup Event Outbox as below: EntityFrameworkCoreModule

[ConnectionStringName(JobManagementServiceDbProperties.ConnectionStringName)]
public class JobManagementServiceDbContext : AbpDbContext<JobManagementServiceDbContext>,
    IHasEventInbox,
    IHasEventOutbox
{
	public JobManagementServiceDbContext(DbContextOptions<JobManagementServiceDbContext> options)
        : base(options)
    {

    }

    public DbSet<IncomingEventRecord> IncomingEvents { get; set; }
    public DbSet<OutgoingEventRecord> OutgoingEvents { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.ConfigureEventInbox();
        builder.ConfigureEventOutbox();
        builder.ConfigureJobManagementService();
    }
}

HostModule

[DependsOn(
    typeof(AbpAspNetCoreSerilogModule),
    typeof(AbpSwashbuckleModule),
    typeof(AbpBackgroundJobsRabbitMqModule),
    typeof(AbpAspNetCoreMultiTenancyModule),
    typeof(AbpDistributedLockingModule),
    typeof(AbpEventBusRabbitMqModule),
    typeof(AbpCachingStackExchangeRedisModule),
private void ConfigureDistributedEventBus()
{
    Configure<AbpDistributedEventBusOptions>(options =>
    {
        options.Inboxes.Configure(config =>
        {
            config.UseDbContext<JobManagementServiceDbContext>();
        });

        options.Outboxes.Configure(config =>
        {
            //config.IsSendingEnabled = false;
            //config.Selector = type => type == typeof(JobOperationEto) || type == typeof(JobConfigurationChangedEto);
            config.UseDbContext<JobManagementServiceDbContext>();
        });
    });
}

I published event as below:

[Authorize(JobManagementServicePermissions.JobConfigurations.Default)]
public class JobConfigurationAppService :
    CrudAppService<JobConfiguration, JobConfigurationDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateJobConfigurationDto>,
    IJobConfigurationAppService
{
    private readonly IDistributedEventBus _distributedEventBus;
    private readonly IUnitOfWorkManager _unitOfWorkManager;

    public JobConfigurationAppService(
        IRepository<JobConfiguration, Guid> repository,
        IDistributedEventBus distributedEventBus,
        IUnitOfWorkManager unitOfWorkManager)
        : base(repository)
    {
        _distributedEventBus = distributedEventBus;
        _unitOfWorkManager = unitOfWorkManager;
    }

    [Authorize(JobManagementServicePermissions.JobConfigurations.Create)]
    public override async Task<JobConfigurationDto> CreateAsync(CreateUpdateJobConfigurationDto input)
    {
        var result = await base.CreateAsync(input);

        await _distributedEventBus.PublishAsync(new JobConfigurationChangedEto
        {
            JobName = input.JobName,
            JobGroup = input.JobGroup,
            TenantId = CurrentTenant.Id,
            IsActive = input.IsActive,
            Description = input.Description,
            JobDataJson = input.JobDataJson,
            CronExpression = input.CronExpression,
            JobType = input.JobType
        });

        return result;
    }

    [Authorize(JobManagementServicePermissions.JobConfigurations.Edit)]
    public override async Task<JobConfigurationDto> UpdateAsync(Guid id, CreateUpdateJobConfigurationDto input)
    {
        var result = await base.UpdateAsync(id, input);

        await _distributedEventBus.PublishAsync(new JobConfigurationChangedEto
        {
            JobName = input.JobName,
            JobGroup = input.JobGroup,
            TenantId = CurrentTenant.Id,
            IsActive = input.IsActive,
            Description = input.Description,
            JobDataJson = input.JobDataJson,
            CronExpression = input.CronExpression,
            JobType = input.JobType
        });

        return result;
    }

    [Authorize(JobManagementServicePermissions.JobConfigurations.Delete)]
    public override async Task DeleteAsync(Guid id)
    {
        var job = await Repository.GetAsync(id);
        await base.DeleteAsync(id);

        await _distributedEventBus.PublishAsync(new JobConfigurationChangedEto
        {
            JobName = job.JobName,
            JobGroup = job.JobGroup,
            TenantId = job.TenantId,
            IsActive = false, // Worker sees this flag and will remove Job from Quartz
            Description = job.Description,
            JobDataJson = job.JobDataJson,
            CronExpression = job.CronExpression,
            JobType = job.JobType
        });
    }

    [Authorize(JobManagementServicePermissions.JobConfigurations.Trigger)]
    public async Task TriggerNowAsync(Guid id)
    {
        var job = await Repository.GetAsync(id);
        await _distributedEventBus.PublishAsync(new JobOperationEto
        {
            JobName = job.JobName,
            JobGroup = job.JobGroup,
            TenantId = job.TenantId,
            ActionType = JobActionType.TriggerNow
        }, useOutbox: false);
    }

    [Authorize(JobManagementServicePermissions.JobConfigurations.Pause)]
    public async Task PauseAsync(Guid id)
    {
        var job = await Repository.GetAsync(id);
        job.IsActive = false;
        await Repository.UpdateAsync(job);

        await _distributedEventBus.PublishAsync(new JobOperationEto
        {
            JobName = job.JobName,
            JobGroup = job.JobGroup,
            TenantId = job.TenantId,
            ActionType = JobActionType.Pause
        });
    }

    [Authorize(JobManagementServicePermissions.JobConfigurations.Resume)]
    public async Task ResumeAsync(Guid id)
    {
        var job = await Repository.GetAsync(id);
        job.IsActive = true;
        await Repository.UpdateAsync(job);

        await _distributedEventBus.PublishAsync(new JobOperationEto
        {
            JobName = job.JobName,
            JobGroup = job.JobGroup,
            TenantId = job.TenantId,
            ActionType = JobActionType.Resume
        });
    }
}

Only TriggerNowAsync method with useOutbox: false work fine, other methods can not publish events. I tried to set config.IsSendingEnabled = false; in HostModule but not found any record in AbpEventOutbox. Please help.

But I still don't understand how each service can call right API to get data. Now I have the menu like this: Service A User Service B User

Please pay attention that all UI are hosted in Web project. When user click in User menu in each service, but it's the same URL, how ABP understand to navigate to different APIs of each service?

OK, let's use Identity module as an example. Now I want to use this module in 2 services concurently. As my understanding, all tables of Identity module will be created in database of each service. Right?

But the code to manage all those tables is located in Identity module. So how to reuse UI in Indentity module and get correct data of Identity module for each service? It means each service will have the same UI, just different data.

That is the problem I'm facing. Please show me your solution to reuse Identity module.

Hi,

In HttpApi I don't have any controller that implement the app service mannualy. The controllers are generated automatically by conventional controllers configured as my previous comment. Do I need to add HttpApi?

For your better suggestion. If I change my code like this:

public class CustomStaticDataTypeAppService : StaticDataTypeAppService, IStaticDataTypeAppService
{
    public CustomStaticDataTypeAppService(IStaticDataTypeRepository staticDataTypeRepository, IStaticDataStructureRepository staticDataStructureRepository, IEmployeeRepository employeeRepository, IStringLocalizer<BaseComponentResource> baselocalizer) : base(staticDataTypeRepository, staticDataStructureRepository, employeeRepository, baselocalizer)
    {
    }
}

It means, if I don't use ICustomStaticDataTypeAppService, use IStaticDataTypeAppService directly, javascript proxy is generate normally. But the problem is APIs will be the same name because it use the same interface, so other services will call wrong APIs of a certain service.

I already configured conventional controller like this but it didn't help:

Configure<AbpAspNetCoreMvcOptions>(options =>
{
    options.ConventionalControllers
        .Create(typeof(AMLReportServiceApplicationModule).Assembly, opts =>
        {
            opts.RootPath = AMLReportServiceRemoteServiceConsts.ModuleName;
            opts.RemoteServiceName = AMLReportServiceRemoteServiceConsts.RemoteServiceName;
        });
});

I have a module named BaseComponent with following AppService:

public interface IStaticDataTypeAppService : IApplicationService
    {
        Task<LoadResult> GetListAsync(DataSourceLoadOptionsCustomized options);
        Task<BaseComponentResponseDto> BatchUpdateAsync(List<DXBatchUpdate> changes);
        Task<StaticDataTypeViewDto?> GetNameByCodeAsync(string code);
    }
    
public class StaticDataTypeAppService : BaseComponentAppService, IStaticDataTypeAppService
    {
        private readonly IStaticDataTypeRepository _staticDataTypeRepository;
        private readonly IStaticDataStructureRepository _staticDataStructureRepository;
        private readonly IEmployeeRepository _employeeRepository;
        private readonly IStringLocalizer<BaseComponentResource> _baseLocalizer;

        public StaticDataTypeAppService(
            IStaticDataTypeRepository staticDataTypeRepository,
            IStaticDataStructureRepository staticDataStructureRepository,
            IEmployeeRepository employeeRepository,
            IStringLocalizer<BaseComponentResource> baselocalizer
        )
        {
            _staticDataTypeRepository = staticDataTypeRepository;
            _staticDataStructureRepository = staticDataStructureRepository;
            _employeeRepository = employeeRepository;
            _baseLocalizer = baselocalizer;
        }
        
        ...
    }

I use this module in AMLReportService as following:

public interface ICustomStaticDataTypeAppService : IStaticDataTypeAppService
{
}

public class CustomStaticDataTypeAppService : StaticDataTypeAppService, ICustomStaticDataTypeAppService
{
    public CustomStaticDataTypeAppService(IStaticDataTypeRepository staticDataTypeRepository, IStaticDataStructureRepository staticDataStructureRepository, IEmployeeRepository employeeRepository, IStringLocalizer<BaseComponentResource> baselocalizer) : base(staticDataTypeRepository, staticDataStructureRepository, employeeRepository, baselocalizer)
    {
    }
}

The purpose that I have to create Custom AppService for IStaticDataTypeAppService is: this module will be used in multiple services, so all of its APIs need to be renamed.

In AMLReportService swagger, I can see custom APs and work fine:

Static C# proxy is also generated normally as following:

[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(ICustomStaticDataTypeAppService), typeof(CustomStaticDataTypeClientProxy))]
public partial class CustomStaticDataTypeClientProxy : ClientProxyBase<ICustomStaticDataTypeAppService>, ICustomStaticDataTypeAppService
{
    public virtual async Task<LoadResult> GetListAsync(DataSourceLoadOptionsCustomized options)
    {
        return await RequestAsync<LoadResult>(nameof(GetListAsync), new ClientProxyRequestTypeValue
        {
            { typeof(DataSourceLoadOptionsCustomized), options }
        });
    }

    public virtual async Task<BaseComponentResponseDto> BatchUpdateAsync(List<DXBatchUpdate> changes)
    {
        return await RequestAsync<BaseComponentResponseDto>(nameof(BatchUpdateAsync), new ClientProxyRequestTypeValue
        {
            { typeof(List<DXBatchUpdate>), changes }
        });
    }

    public virtual async Task<StaticDataTypeViewDto> GetNameByCodeAsync(string code)
    {
        return await RequestAsync<StaticDataTypeViewDto>(nameof(GetNameByCodeAsync), new ClientProxyRequestTypeValue
        {
            { typeof(string), code }
        });
    }
}

But in client side, in ServiceProxyScript, I can't find those APIs, I don't know why it's not generated (Only APIs in BaseComponent module are not generated, other APIs in AMLReportService are generated normally). Please help.

Hi,

So, when dynamic claim is called? Every 1 hour?

Hi,

I fixed this issue by adding this code in WebModule to change Dynamic Claim URL for internal call in K8s

context.Services.Configure<AbpClaimsPrincipalFactoryOptions>(options =>
{
    options.IsDynamicClaimsEnabled = true;
    options.RemoteRefreshUrl = configuration["AuthServer:MetadataAddress"] + options.RemoteRefreshUrl.Replace(configuration["AuthServer:Authority"],""); --> ADDED THIS LINE
});

But can you explain why dynamic claim impact to Access Token lifetime?

Hi,

Already sent identitymodel.txt. Please check.

Showing 1 to 10 of 93 entries
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.2.0-preview. Updated on February 05, 2026, 13:24
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.