using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Identity;
using Volo.Abp.Identity.Settings;
using Volo.Abp.Settings;
namespace Volo.Abp.Account.Emailing;
public class AccountIdentityUserCreatedEventHandler :
IDistributedEventHandler<IdentityUserCreatedEto>,
ITransientDependency
{
protected IdentityUserManager UserManager { get; }
protected IAccountEmailer AccountEmailer { get; }
protected ISettingProvider SettingProvider { get; }
public AccountIdentityUserCreatedEventHandler(
IdentityUserManager userManager,
IAccountEmailer accountEmailer,
ISettingProvider settingProvider)
{
UserManager = userManager;
AccountEmailer = accountEmailer;
SettingProvider = settingProvider;
}
public async Task HandleEventAsync(IdentityUserCreatedEto eventData)
{
if (eventData.Properties["SendConfirmationEmail"] == true.ToString().ToUpper() &&
await SettingProvider.IsTrueAsync(IdentitySettingNames.SignIn.RequireConfirmedEmail))
{
var user = await UserManager.GetByIdAsync(eventData.Id);
var confirmationToken = await UserManager.GenerateEmailConfirmationTokenAsync(user);
await AccountEmailer.SendEmailConfirmationLinkAsync(user, confirmationToken,
eventData.Properties.GetOrDefault("AppName") ?? "MVC");
}
}
}
This code doesn't work when using RabbitMQ, because there is no tenant context here when i do it will InMemory then it works but when i add rabbitmq it is not fetching SettingProvider.IsTrueAsync(IdentitySettingNames.SignIn.RequireConfirmedEmail) because it using null tenant context.
Is there a quick fix for this also are there any similar issue like this?
2 Answer(s)
-
0
- Solution
Root cause: When using the distributed event bus (RabbitMQ), the handler runs in a background consumer without an HTTP scope, so there is no ambient tenant set automatically. IdentityUserCreatedEto contains TenantId; you must set the tenant context for the duration of your handler to resolve tenant-scoped services/settings correctly.
Quick fix (wrap the handler body in ICurrentTenant.Change):
using Volo.Abp.MultiTenancy; public class AccountIdentityUserCreatedEventHandler : IDistributedEventHandler<IdentityUserCreatedEto>, ITransientDependency { protected IdentityUserManager UserManager { get; } protected IAccountEmailer AccountEmailer { get; } protected ISettingProvider SettingProvider { get; } protected ICurrentTenant CurrentTenant { get; } public AccountIdentityUserCreatedEventHandler( IdentityUserManager userManager, IAccountEmailer accountEmailer, ISettingProvider settingProvider, ICurrentTenant currentTenant) { UserManager = userManager; AccountEmailer = accountEmailer; SettingProvider = settingProvider; CurrentTenant = currentTenant; } public async Task HandleEventAsync(IdentityUserCreatedEto eventData) { using (CurrentTenant.Change(eventData.TenantId)) { if (eventData.Properties["SendConfirmationEmail"] == true.ToString().ToUpper() && await SettingProvider.IsTrueAsync(IdentitySettingNames.SignIn.RequireConfirmedEmail)) { var user = await UserManager.GetByIdAsync(eventData.Id); var confirmationToken = await UserManager.GenerateEmailConfirmationTokenAsync(user); await AccountEmailer.SendEmailConfirmationLinkAsync( user, confirmationToken, eventData.Properties.GetOrDefault("AppName") ?? "MVC" ); } } } }This ensures SettingProvider (and any tenant-scoped logic like repositories, feature checks, etc.) work under the correct tenant.
If you need host-level settings for some reason, wrap only the required code block with Change(null).
Notes:
- In-memory distributed bus handlers run in-process and may inherit the ambient tenant from the publisher scope; RabbitMQ consumers don’t, so you must explicitly set it.
- IdentityUserCreatedEto includes TenantId; rely on it to set the tenant scope before accessing tenant-scoped services.
- Sources
- https://abp.io/docs/latest/framework/infrastructure/event-bus/distributed/rabbitmq
- https://abp.io/community/articles/daf47e17
- https://abp.io/community/articles/ax1lgvxf
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.
-
0
But there is no TenantId in the IdentityUserCreatedEto.
I have resolved this but wanted to know if there are more issues like this with the eventhandlers tenant context issues as these are hard to debug
or is there any configuration i missed from my side, i need to know please let me know.