Open Closed

User Registeration in multi tenancy application #171


0
mohamed emaish created

Dear Halil,

i'm trying to create a user registration method in a multi tenancy application, i get current tenant id by tenancy name, when i try to set tenant id for user i get exception "Can not set TenantId to a different value than the current filter parameter value or IAbpSession.TenantId while MayHaveTenant filter is enabled", i disabled AbpDataFilters.MayHaveTenant but the exception still exist.

What is missing ?


4 Answer(s)
  • 0
    hikalkan created
    Support Team

    Hi,

    I will share a simplified version of AspNet Zero's registration code for you:

    [HttpPost]
    [UnitOfWork]
    public virtual async Task<ActionResult> Register(RegisterViewModel model)
    {
        try
        {
            if (!_multiTenancyConfig.IsEnabled)
            {
                model.TenancyName = Tenant.DefaultTenantName;
            }
            else if (model.TenancyName.IsNullOrEmpty())
            {
                throw new UserFriendlyException(L("TenantNameCanNotBeEmpty"));
            }
    
            var tenant = await GetTenantAsync(model.TenancyName);
    
            var user = new User
            {
                TenantId = tenant.Id,
                Name = model.Name,
                Surname = model.Surname,
                UserName = model.UserName,
                EmailAddress = model.EmailAddress,
                Password = new PasswordHasher().HashPassword(model.Password),
                IsActive = true
            };
    
            _unitOfWorkManager.Current.EnableFilter(AbpDataFilters.MayHaveTenant);
            _unitOfWorkManager.Current.SetFilterParameter(AbpDataFilters.MayHaveTenant, AbpDataFilters.Parameters.TenantId, tenant.Id);
    
            user.Roles = new List<UserRole>();
            foreach (var defaultRole in await _roleManager.Roles.Where(r => r.IsDefault).ToListAsync())
            {
                user.Roles.Add(new UserRole { RoleId = defaultRole.Id });
            }
    
            CheckErrors(await _userManager.CreateAsync(user));
            await _unitOfWorkManager.Current.SaveChangesAsync();
    
            //Directly login
            var loginResult = await GetLoginResultAsync(user.UserName, model.Password, tenant.TenancyName);
            if (loginResult.Result == AbpLoginResultType.Success)
            {
                await SignInAsync(loginResult.User, loginResult.Identity);
                return Redirect(Url.Action("Index", "Application"));
            }
        }
        catch (UserFriendlyException ex)
        {
            ViewBag.ErrorMessage = ex.Message;
            return View(model);
        }
    }
    

    I hope this helps you and others.

  • 0
    mohamed emaish created

    Thank you Dear :)

  • 0
    omital created

    <cite>hikalkan: </cite> Hi,

    I will share a simplified version of AspNet Zero's registration code for you:

    [HttpPost]
    [UnitOfWork]
    public virtual async Task<ActionResult> Register(RegisterViewModel model)
    {
       try
       {
           if (!_multiTenancyConfig.IsEnabled)
           {
               model.TenancyName = Tenant.DefaultTenantName;
           }
           else if (model.TenancyName.IsNullOrEmpty())
           {
               throw new UserFriendlyException(L("TenantNameCanNotBeEmpty"));
           }
    
           var tenant = await GetTenantAsync(model.TenancyName);
    
           var user = new User
           {
               TenantId = tenant.Id,
               Name = model.Name,
               Surname = model.Surname,
               UserName = model.UserName,
               EmailAddress = model.EmailAddress,
               Password = new PasswordHasher().HashPassword(model.Password),
               IsActive = true
           };
    
           _unitOfWorkManager.Current.EnableFilter(AbpDataFilters.MayHaveTenant);
           _unitOfWorkManager.Current.SetFilterParameter(AbpDataFilters.MayHaveTenant, AbpDataFilters.Parameters.TenantId, tenant.Id);
    
           user.Roles = new List<UserRole>();
           foreach (var defaultRole in await _roleManager.Roles.Where(r => r.IsDefault).ToListAsync())
           {
               user.Roles.Add(new UserRole { RoleId = defaultRole.Id });
           }
    
           CheckErrors(await _userManager.CreateAsync(user));
           await _unitOfWorkManager.Current.SaveChangesAsync();
    
           //Directly login
           var loginResult = await GetLoginResultAsync(user.UserName, model.Password, tenant.TenancyName);
           if (loginResult.Result == AbpLoginResultType.Success)
           {
               await SignInAsync(loginResult.User, loginResult.Identity);
               return Redirect(Url.Action("Index", "Application"));
           }
       }
       catch (UserFriendlyException ex)
       {
           ViewBag.ErrorMessage = ex.Message;
           return View(model);
       }
    }
    

    I hope this helps you and others.

    I have this problem too. but I use SPA version with angularjs. Is your solution difference ? I cant find _multiTenancyConfig in application layer

    Edit: I think AbpSession that injected to application service for this purpose?! Is it true?

  • 0
    hikalkan created
    Support Team

    Hi,

    Did you checked module-zero template? See <a class="postlink" href="https://github.com/aspnetboilerplate/module-zero-template/blob/master/src/AbpCompanyName.AbpProjectName.WebSpaAngular/Controllers/AccountController.cs">https://github.com/aspnetboilerplate/mo ... troller.cs</a> It's a working code.

    BTW, Just inject IMultiTenancyConfig (as _multiTenancyConfig) if you need.