Open Closed

AbpSession.Use and UnitOfWorkManager.Current.SetTenantId #3932


0
arnoldkesselaar created

Hi Everyone,

I am utilising the "multi-tenant, multi-db" scenario.

Consider the following function.

#1 The line with UserManager.ConfirmEmailAsync will not work without the using statement above it. It can't find the correct tenanted user.

#2 The line with await UserManager.UpdateAsync(user) doesn't work without the UnitOfWorkManager.Current.SetTenantId using statement above it.

I would have thought that #2 being within the scope of #1 would be ok without the extra using statement. Why do I need to do this?

[AbpAllowAnonymous]
        [UnitOfWork]
        public async Task<SecureUserResultDto> ActivateUser(SecureUserDto userDto)
        {
            var activationResult = new SecureUserResultDto();

            var user = await GetTenantedUser(userDto.UserEmail);

            if (user != null)
            {
                using (AbpSession.Use(user.TenantId, user.Id))
                {
                    var result = await UserManager.ConfirmEmailAsync(user, userDto.SecurityToken);
                    if (result.Succeeded)
                    {
                        user.IsEmailConfirmed = true;
                        user.IsActive = true;
                        user.Password = HashUserPassword(user, userDto.Password);

                        try
                        {
                            using (UnitOfWorkManager.Current.SetTenantId(user.TenantId))
                                await UserManager.UpdateAsync(user);

                            activationResult.Success = true;
                            activationResult.UserEmail = user.EmailAddress;
                        }
                        catch (Exception e)
                        {
                            activationResult.Errors = new List<string>();
                            activationResult.Errors.Add(e.Message);
                        }

2 Answer(s)
  • 0
    aaron created
    Support Team

    #1 The line with UserManager.ConfirmEmailAsync will not work without the using statement above it. It can't find the correct tenanted user.

    You need AbpSession.Use if the current user is not in the same tenant as the user whose email you want to confirm.

    #2 The line with await UserManager.UpdateAsync(user) doesn't work without the UnitOfWorkManager.Current.SetTenantId using statement above it.

    I would have thought that #2 being within the scope of #1 would be ok without the extra using statement. Why do I need to do this?

    AbpSession.Use only sets TenantId and UserId in AbpSession. These values are used when you begin a UnitOfWork (UOW). However, since you are already in a UOW, calling AbpSession.Use does not automatically set TenantId in the current UOW.

  • 0
    tusksoft created

    So is that to say that if you're using implicit/automatic UoW management you always need to use UnitOfWorkManager.Current.SetTenantId and when you're managing your on UoW you can use AbpSession.Use before the UoW begins to achieve the same effect? If that's correct, is there a reason to have two separate methods instead of just one? Is there a useful scenario for this?