ASP MVC EF6 Code first Multi tenant get tenant id

401 views Asked by At

we keep fighting with out multi tenant application. This is an ASP MVC EF6 Code First web application.

We initialize a list of tenants in the Application_Start, getting a pair of values:

Host
TenantId

So we can associate any host with one TenantId, and store that list in cache.

We have configured a custom filter to get the current tenant.

public class TenantActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.HttpContext.Items.Add("TenantId", GetCurrentTenant(filterContext.HttpContext.Request.Url.Host));

        base.OnActionExecuting(filterContext);
    }
}

The GetCurrentTenant function just access the list in cache and get the current one based on the host passed.

Is it correct to store the current tenant in an item in the context?

After that, we have created an Interceptor to get any query and add a filter to filter by TenantId. This is done and working good, we just need to add the tenantId from the context:

The problem we have is where we get the TenantId for each request.

if (HttpContext.Current.CurrentHandler == null) return;
var clientId = Convert.ToInt32(HttpContext.Current.Items["ClientId"]);

        foreach (DbParameter param in command.Parameters)
        {
            if (param.ParameterName != TenantAwareAttribute.TenantIdFilterParameterName)
                continue;
            param.Value = clientId;
        }

We don't know if this is the correct approach since there is a lot of informationon the net.

Thanks.

1

There are 1 answers

0
Saravanan On

In my experience, the persistence of the tenant Id in the HTTP context is not right, as in some cases, the HTTP context becomes null.

You can try to get the tenant Id from the claims of the current principal. Creating a static class with a tenant identifier property that reads from the claims and gives is more reliable. Assuming you are using the owin pipeline, this should be easy to do. You can take a look at the reference sample application from github here

It looks like the below block,

public static class UserContext
{
   public static string TenantId
   {
       get
       {
           return Threading.Thread.CurrentPrincipal.FindFirst("tenantid");
       }
   }
}