I'm building a multitenant asp.net core 3.1 app with several database (one for each tenant and one master database). I'm using Autofac for having the Singleton per tenant lifetime support for my services (for now i'm not need the tenant override, i need only the custom SinglePerTenant lifetime) I'm using
My tenant identification strategy involve a db call to the master database.
As written in the documentation of autofac, the identification strategy should not have calls to the database since it is called at each dependency resolution. Then i used another solution for tenant identification (Finbuckle.MultiTenant).
With Finbukle when a request arrives his identification strategy is called (once per htp request), i put the db call in his identification strategy (for optimization i can cache the result, and refresh the query once a day) and a tenantInfo object is set in the HttpContext.
Then In the AutoFac identification strategy i try to read the object setted by FinBuckle, but is not possibile because the Autofac identification Strategy is called before the FinBuckle ones and the desidered property is null.
My Program.cs is:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacMultitenantServiceProviderFactory(Startup.ConfigureMultitenantContainer))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Startup.cs :
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMultiTenant().WithStrategy<TestStategy>(ServiceLifetime.Singleton).WithStore<CustomTestStore>(ServiceLifetime.Singleton); //enable the multitenant support from finbukle
services.AddControllers();
services.AddAutofacMultitenantRequestServices();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseMultiTenant() //finbukle
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<TestDiA>().As<ITestDI>().InstancePerTenant();
}
public static MultitenantContainer ConfigureMultitenantContainer(IContainer container)
{
// This is the MULTITENANT PART. Set up your tenant-specific stuff here.
var strategy = new MyAutofacTenantIdentificationStrategy(container.Resolve<IHttpContextAccessor>());
var mtc = new MultitenantContainer(strategy, container);
return mtc;
}
}
Autofac tenant identification strategy:
public class MyAutofacTenantIdentificationStrategy : ITenantIdentificationStrategy
{
private readonly IHttpContextAccessor httpContextAccessor;
public MyAutofacTenantIdentificationStrategy(
IHttpContextAccessor httpContextAccessor
)
{
this.httpContextAccessor = httpContextAccessor;
}
public bool TryIdentifyTenant(out object tenantId)
{
tenantId = null;
var context = httpContextAccessor.HttpContext;
if (context == null)
return false;
var identifier = context.getTenatInfo()?.Identifier ?? null; //getTenantInfo is a method that extract the tenant info object setted by finbukle
tenantId = identifier;
return (tenantId != null || tenantId == (object)"");
}
}
I'm using Autofac.AspNetCore.Multitenant 3.0.0, Autofac.Extensions.DependencyInjection 6.0.0 and FinBuckle.MultiTenant 5.0.4
I'm really new in this area, so I apologize if I ask a trivial question. There is a way of solving the problem with this approach?
Or there is an alternative strategy for my Issue?