Skip to content
This repository has been archived by the owner on Jul 26, 2019. It is now read-only.

unosquare/tenantcore

Repository files navigation

NuGet version Build Status Analytics

TenantCore

Important - This repository has been archived. We are not longer maintaining this project.

TenantCore is an OWIN Middleware that it can help to resolve tenants, a multitenancy middleware, by request's hostname for example or by any resolver. You can create your own Tenant's resolver or use the default one. The tenant can have a database connection string or any property that you need.

To start you need to setup the Resolver and Tenants in your OWIN AppBuilder, for example:

public void ConfigureAuth(IAppBuilder app)
{
    // SetUp Multitenancy with TenantCore
    var tenants = new List<ITenant>
    {
        new Tenant("local", "localhost", @"Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\local.mdf;Initial Catalog=local;Integrated Security=True"),
        new Tenant("sample", "sample.local", @"Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\sample.mdf;Initial Catalog=sample;Integrated Security=True"),
        new Tenant("fake", "fake.local", @"Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\fake.mdf;Initial Catalog=fake;Integrated Security=True")
    };
            
    app.UseTenantCore(new HostNameTenantResolver(tenants));

    // Configure the db context and user manager to use a single instance per request
    app.CreatePerOwinContext<ApplicationDbContext>(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

    // And continue with your middleware and settings
}

If you want to have a database per tenant, you need to change your DbContext or IdentityDbContext to have a Create method with parameters:

public static ApplicationDbContext Create(IdentityFactoryOptions<ApplicationDbContext> options,
    IOwinContext context)
{
    return context.GetDbContext<ApplicationDbContext>();
}

The GetDbContext is an extension method in TenantCore, it will find the current Tenant and get the ConnectionString. The ConnectionString will be used with your DbContext, so be sure to have a constructor with connectionstring param like this:

public ApplicationDbContext(string connectionString)
            : base(connectionString, throwIfV1Schema: false) {}

Now in your ApiController you can use the Tenant or DbContext with some extension methods, for example:

[HttpGet, Route("register/{id}")]
public async Task<IHttpActionResult> Register(string id)
{
    // Gets the DbContext related to current Tenant
    var database = HttpContext.Current.GetDbContext<ApplicationDbContext>();
    // Gets the current Tenant
    var tenant = HttpContext.Current.GetCurrentTenant();
}