I'm trying to find the best way for a multi-tenancy setup for an application. I would like to have a single database for the clients with a TenantId on each table with a single table with all the tenants information. Ex. Db Tenant Table(TenantId, Code, Name, etc)
I have a base controller for all my WebApi Controllers and MVC Controllers(WebApiBaseController and AppBaseController). I would like for these two controllers to filer the results based on the current user tenantId.
Should the DbContext to take care of this? I do want to have a
users.Where(u => u.TenantId == CurrenctUser.TenantId)
everywhere.
I also looked at this question, but i think it is a different problem hes trying to solve.
For this project I am using: ASP.NET MVC 5 WebApi 2 Entity Framework 6 AspNet.Identity
How do I filter entities based on currently logged in users using their tenantId on a single location?
UPDATE
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
Database.SetInitializer<ApplicationDbContext>(null);
}
public DbSet<Tenant> Tenants { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new TenantMap());
modelBuilder.Configurations.Add(new ApplicationUserMap());
// Create parameterized filter for all entities that match type ITenantEntity
modelBuilder.Filter(Infrastructure.Constants.TetantFilterName, (ITenantEntity b) => b.TenantId, () => string.Empty);
// By default the filter is disable to allow unauthenticated users to login
// FIX: This filter must be Enabled at the base controller for mvc and webapi
// basically, it will only get activated after the user logs in. See Base Controllers
modelBuilder.DisableFilterGlobally(Infrastructure.Constants.TetantFilterName);
base.OnModelCreating(modelBuilder);
}
public void EnableTenantFilter()
{
this.EnableFilter(Infrastructure.Constants.TetantFilterName);
}
public void DisableTenantFilter()
{
this.DisableFilter(Infrastructure.Constants.TetantFilterName);
}
}
[Authorize]
public class WebApiBaseController : ApiController
{
ApplicationUser _currectUser;
public ApplicationUser CurrentUser
{
get
{
if (_currectUser == null)
{
AppDb.DisableTenantFilter();
string currentUserId = User.Identity.GetUserId();
_currectUser = AppDb.Users.FirstOrDefault(a => a.Id == currentUserId);
AppDb.EnableTenantFilter();
}
return _currectUser;
}
set { _currectUser = value; }
}
public ApplicationDbContext AppDb
{
get;
private set;
}
public WebApiBaseController(ApplicationDbContext context)
{
AppDb = context;
if (User.Identity.IsAuthenticated)
{
AppDb.SetFilterGlobalParameterValue(Infrastructure.Constants.TetantFilterName, CurrentUser.TenantId);
}
}
}