I'm developing a multi-tenant application in .NET and I've run into an issue where I need to access a scoped service, ITenantProvider, from within a custom middleware, TenantMiddleware. However, when I try to run my application, I receive the following error:
Cannot resolve scoped service 'MyNameSpace.ITenantProvider' from root provider.
Here is the middleware:
public class TenantMiddleware
{
private readonly RequestDelegate _next;
private readonly ITenantProvider _tenantProvider;
public TenantMiddleware(ITenantProvider tenantProvider, RequestDelegate next)
{
_tenantProvider = tenantProvider;
_next = next;
}
public async Task Invoke(HttpContext context)
{
// Logic to set tenant ID
await _next(context);
}
}
Startup config:
services.AddScoped<ITenantProvider, TenantProviderImplementation>();
builder.Services.AddTransient<IDBService, DBService>();
app.UseMiddleware<TenantMiddleware>();
The goal of the tenant ITenantProvider is to be set with a tenant Id (as a scoped) and the to be consumed by other services while it is injected as scoped to a transient db services.
public interface ITenantProvider
{
public Guid GetTenantId();
public void SetTenantId(Guid tenantId);
}
The DBService has the tenantId provider as a dependancy:
DbService(ITenantProvider tenant) { ... }
The most imprtant thing that the method DbLogic will be able to get from the injected ITenantProvider the tenantId via the method GetTenantId() that is correspondent with the one-time-called method (via the middleware) of SetTenantId(Guid tenantId)
DbLogic()
{
Guid tenantId = _tenantProvider.GetTenantId();
}
I understand that the issue is related to trying to inject a scoped service (ITenantProvider) into a middleware that is a singleton, but I'm not sure how to correctly structure this to avoid the error.
You can resolve it from the context in the
Invokecall (remove the ctor parameter):Or inject it directly to the method parameters: