I have a multi-tenant ASP.NET Core web application. The current tenancy model is every tenant has a separate web app and SQL database. I'm trying to rearchitect it so that multiple tenants will be served by a single web app (but maintaining a separate database per tenant). I've been following this series of blog posts but I've hit a bit of a roadblock with configuration.
The app makes heavy use of the ASP.NET Core configuration system, and has a custom EF Core provider that fetches config values from the database. I'd like to preserve this if possible, it would be an awful lot of work to rip out and replace with something else (dozens of config settings used in hundreds of places).
The existing code is very standard:
public class MyAppSettings
{
public string FavouriteColour { get; set; }
public int LuckyNumber { get; set; }
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.Configure<MyAppSettings>(Configuration.GetSection("MyAppSettings"));
// etc....
}
}
// custom EF Core config provider wired up in Program.Main, but that doesn't actually seem relevant
I've already updated our custom provider so that it fetches all configuration values from all known tenant databases, and adds them all to the configuration system, prefixed with a tenant identifier, so the list of all config values fetched from the n different databases might look something like this:
Key Value
===============================================
TenantABC:MyAppSettings:FavouriteColour Green
TenantABC:MyAppSettings:LuckyNumber 42
TenantDEF:MyAppsettings:FavouriteColour Blue
TenantDEF:MyAppSettings:LuckyNumber 37
...
TenantXYZ:MyAppSettings:FavouriteColour Yellow
TenantXYZ:MyAppSettings:LuckyNumber 88
What I'd like to be able to do is somehow customise the way that the configuration is bound so that it resolves the tenant for the current request, and then uses the appropriate values, e.g. a request on abc.myapp.com would observe config values "Green" and "42", etc, without having to change all the dependent places that inject IOptionsMonitor<AppSettings>
(or IOptionsSnapshot
, etc). The linked blog series has a post about configuration that covers some gotchas that I expect I'll eventually run into around caching etc, but it doesn't seem to cater for this scenario of using completely different settings for different tenants. Conceptually it seems simple enough, but I haven't been able to find the correct place to hook in. Please help!