scojomodena
scojomodena

Reputation: 842

Access TenantId in Model Project in ASP.NET MVC

I am moving an app from single tenant to multi-tenant. In the process, I added tenantId to all the required models and updated the database (Entity Framework 5).

However, I have all the repositories that need updating. First, I don't know how to get the current user id (then tenantId) in the Model Project (not dependent on WebSecurity, no httpContext).

Second, I don't want to have to do this ugly/expensive code in all my controllers. (Get UserId, make a database call to get the tenantId, then pass that to the Repository.)

public class PinTypeController : BaseController
{
    private PinTypeRepository pinTypeRepo;

    public PinTypeController()
    {
        UserRepository userRepo = new UserRepository();
        UserProfile user = userRepo.GetById(WebSecurity.CurrentUserId);
        this.pinTypeRepo = new PinTypeRepository(user.TenantId);
    }

    public ActionResult Index()
    {
        vmPinType vm = new vmPinType();
        vm.NewPinType = new PinType();
        vm.PinTypes = pinTypeRepo.GetAll();
        return View(vm);
    }
}

Is there a better way to store the tenantId in a way that I can access it from the Model Project and all my repositories?

Upvotes: 3

Views: 1395

Answers (1)

SebastianStehle
SebastianStehle

Reputation: 2459

I would decouple where the tenant id is coming from, from the rest of your code, for example you could support multiple domains where one tenant is mapped to a domain.

In my project I defined an interface

interface ITenantProvider
{
    Tenant Tenant { get; }
}

And the implementation:

class TenantProvider : ITenantProvider
{   
    Tenant Tenant
    {
        get
        {
            Tenant tenant = HttpContent.Current.Items["Tenant"] as Tenant;
            if (tenant == null)
            {
                string domain = GetDomain();
                tenant = TenantRepository.GetTenantByDomain(domain);
                HttpContext.Current.Items["Tenant"] = tenant;
            }
            return tenant;
        }
    }
}

I cache the tenant in the items-dictionary, so I can access the tenant as often as I want per request and dont get any performane issues.

If each user has a custom tenant it is not a problem, because you just have to change the interface. You could also add more complex logic, e.g. in my frontend the tenant is defined by url and in the admin-area there is a route-parameter for the tenant-id.

Upvotes: 6

Related Questions