An Unobtrusive Multitenancy helper for (new or existing) Asp.Net Core project
The goal of this project is to add the multitenancy functionality to an ASP.NET Core application (existing or new) without modification (or very little) of code.
It's support multitenant DI ,sandbox services, etc.
Just add a line in the Program.cs and add a configuration file.
And voila your application is multitenant.
Inspired by saaskit and Explanation of multitenancy with autofac in ASP.NET Core.
Build server | Platform | Build status |
---|---|---|
AppVeyor | Windows | |
Travis | Linux / OS X |
- Per Tenant Middleware
- Per Tenant DI
- Per Tenant Services
- Per Tenant HostingEnvironment
- Per Tenant Configuration
- Per Tenant Logging
- Add/Update/Delete on fly without restart
Package nuget coming soon.
Before you need to add MultitenancyOptions.json
config file either at the Root folder or in the Configs folder or provide your own configuration object which contains MultitenancyOptions
Replace this line .UseStartup<Startup>()
in your Program.cs
like in example below.
{
"MultitenancyOptions": {
"Tenants": [
{
"Name": "Tenant 1",
"Hostnames": [
"localhost:47887",
...
],
"Theme": "",
"ConnectionString": ""
},
{
"Name": "Tenant 2",
"Hostnames": [
...
"localhost:60001"
],
"Theme": "",
"ConnectionString": ""
}
]
}
}
N.B: If MultitenancyOptionsnot found ,it will fallback to default .UseStartup<Startup>()
You have two options :
- Use Default Conventions
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseUnobtrusiveMulitenancyStartupWithDefaultConvention<Startup>()
.Build();
}
With this , you have an access to an object name AppTenant
and you can add use this in your views. In your _ViewImports.cshtml
@inject Puzzle.Core.Multitenancy.Internal.AppTenant Tenant;
In cshtml files you can use tenant like this:
<a asp-controller="Home" asp-action="Index" class="navbar-brand">@(Tenant?.Name ?? "")</a>
- Use YourCustom Configuration
Use this signature, and provide your own TTenant
and TResolver
public static IWebHostBuilder UseUnobtrusiveMulitenancyStartup<TStartup, TTenant, TResolver>
(this IWebHostBuilder hostBuilder, IConfiguration multitenancyConfiguration = null)
where TStartup : class
where TTenant : class
where TResolver : class, ITenantResolver<TTenant>
And after use your own tenant in your view like in option 1.
The result is :
Add a method call ConfigurePerTenantServices
in your Startup
class and you have access in TENANT.
See example below:
public void ConfigurePerTenantServices(IServiceCollection services, AppTenant tenant)
{
if (tenant.Id == "Tenant-1".ToLowerInvariant())
{
services.AddMvc();
}
else if (tenant.Id == "Tenant-2".ToLowerInvariant())
{
}
}
public void Configure(IApplicationBuilder application, IApplicationLifetime appLifetime)
{
application.UseStaticFiles();
application.UsePerTenant<AppTenant>((tenantContext, builder) =>
{
if (tenantContext.Tenant.Id == "Tenant-1".ToLowerInvariant())
{
builder.UseMvcWithDefaultRoute();
}
else if (tenantContext.Tenant.Id == "Tenant-2".ToLowerInvariant())
{
builder.Run(async ctx =>
{
ctx.Response.StatusCode = (int)HttpStatusCode.OK;
await ctx.Response.WriteAsync(string.Format("{0} Without MVC", tenantContext.Tenant.Name));
});
}
});
}
In example project if you try to UseMvc work for Tenant 2
you will get this error :