Base solution for your next web application
Open Closed

Extend Tenant to have a domain #1858


User avatar
0
roxybox created

I have added a domain property to the Tenant class and have replicated the ITenantCache implementation to now have Get(string domain) instead of Get(string tenancyName).

After making all the changes so it looks up the tenant based on the domain instead of the tenancy name I am unable to get access to the new Domain property.

<ins>protected virtual TTenant GetTenantOrNull(string domain)
        {
            using (_unitOfWorkManager.Current.SetTenantId(null))
            {
                return _tenantRepository.FirstOrDefault(t => t.**[u]_Domain_</ins>**== domain);
            }
        }

I have the same issue for the below

protected virtual RbTenantCacheItem CreateRbTenantCacheItem(TTenant tenant)
        {
            return new RbTenantCacheItem
            {
                Id = tenant.Id,
                Name = tenant.Name,
                TenancyName =  tenant.TenancyName,
                Domain = tenant.<ins>_**Domain**_</ins>,
                EditionId = tenant.EditionId,
                ConnectionString = SimpleStringCipher.Instance.Decrypt(tenant.ConnectionString),
                IsActive = tenant.IsActive
            };
        }

Below is the full class

public class TenantCache<TTenant, TUser> : IRbTenantCache, IEventHandler<EntityChangedEventData<TTenant>>
        where TTenant : AbpTenant<TUser>
        where TUser : AbpUser<TUser>
    {
        private readonly ICacheManager _cacheManager;
        private readonly IRepository<TTenant> _tenantRepository;
        private readonly IUnitOfWorkManager _unitOfWorkManager;

        public TenantCache(
            ICacheManager cacheManager,
            IRepository<TTenant> tenantRepository,
            IUnitOfWorkManager unitOfWorkManager)
        {
            _cacheManager = cacheManager;
            _tenantRepository = tenantRepository;
            _unitOfWorkManager = unitOfWorkManager;
        }

        public virtual RbTenantCacheItem Get(int tenantId)
        {
            var cacheItem = GetOrNull(tenantId);

            if (cacheItem == null)
            {
                throw new AbpException("There is no tenant with given id: " + tenantId);
            }

            return cacheItem;
        }

        public virtual RbTenantCacheItem Get(string domain)
        {
            var cacheItem = GetOrNull(domain);

            if (cacheItem == null)
            {
                throw new AbpException("There is no tenant with given tenancy name: " + domain);
            }

            return cacheItem;
        }

        public virtual RbTenantCacheItem GetOrNull(string domain)
        {
            var tenantId = _cacheManager.GetTenantByNameCache()
                .Get(domain, () => GetTenantOrNull(domain)?.Id);

            if (tenantId == null)
            {
                return null;
            }

            return Get(tenantId.Value);
        }

        public RbTenantCacheItem GetOrNull(int tenantId)
        {
            return _cacheManager
                .GetTenantCache()
                .Get(
                    tenantId,
                    () =>
                    {
                        var tenant = GetTenantOrNull(tenantId);
                        if (tenant == null)
                        {
                            return null;
                        }

                        return CreateRbTenantCacheItem(tenant);
                    }
                );
        }

        protected virtual RbTenantCacheItem CreateRbTenantCacheItem(TTenant tenant)
        {
            return new RbTenantCacheItem
            {
                Id = tenant.Id,
                Name = tenant.Name,
                TenancyName =  tenant.TenancyName,
                Domain = tenant.Domain,
                EditionId = tenant.EditionId,
                ConnectionString = SimpleStringCipher.Instance.Decrypt(tenant.ConnectionString),
                IsActive = tenant.IsActive
            };
        }

        [UnitOfWork]
        protected virtual TTenant GetTenantOrNull(int tenantId)
        {
            using (_unitOfWorkManager.Current.SetTenantId(null))
            {
                return _tenantRepository.FirstOrDefault(tenantId);
            }
        }

        [UnitOfWork]
        protected virtual TTenant GetTenantOrNull(string domain)
        {
            using (_unitOfWorkManager.Current.SetTenantId(null))
            {
                return _tenantRepository.FirstOrDefault(t => t.Domain == domain);
            }
        }

        public void HandleEvent(EntityChangedEventData<TTenant> eventData)
        {
            var existingCacheItem = _cacheManager.GetTenantCache().GetOrDefault(eventData.Entity.Id);

            _cacheManager
                .GetTenantByNameCache()
                .Remove(
                    existingCacheItem != null
                        ? existingCacheItem.TenancyName
                        : eventData.Entity.TenancyName
                );

            _cacheManager
                .GetTenantCache()
                .Remove(eventData.Entity.Id);
        }
    }

3 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Instead of using

    where TTenant : AbpTenant<TUser>
    

    can you try with

    where TTenant : Tenant
    

    in your custom tenant cache class ?

  • User Avatar
    0
    roxybox created

    Thanks for pointing that out.

    One more question. If I wanted to use this class with IOC where should I register it (if I need to) and do I have to use the constructor approach or is there another way to use the class?

    I have created a filter to retrieve the cached version of the Tenant using the domain. Alternatively, if I have to use the constructor approach I will have to put it in the in the base controller.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    You can derive your class from ISingletonDependency or ITransientDependency. It will be registered to DI automatically by ABP.

    If you want to do it manually, you can do it in the Initialize of your ABP module using IocManager.

    Other than constructor injection there is property injection which you can use. You can find more info about Dependency Injection here <a class="postlink" href="http://aspnetboilerplate.com/Pages/Documents/Dependency-Injection">http://aspnetboilerplate.com/Pages/Docu ... -Injection</a>

    it's better to use constructor injection most of the times.