I’m implementing StructureMap in a multi-tenant ASP.NET MVC application to inject instances of my tenant repositories that retrieve data based on an ITenantContext interface. The Tenant in question is determined from RouteData in a base controller’s OnActionExecuting.
How do I tell StructureMap to construct TenantContext(tenantID); where tenantID is derived from my RouteData or some base controller property?
Base Controller
Given the following route:
{tenant}/{controller}/{action}/{id}
My base controller retrieves and stores the correct Tenant based on the {tenant} URL parameter. Using Tenant, a repository with an ITenantContext can be constructed to retrieve only data that is relevant to that tenant.
Based on the other DI questions, could AbstractFactory be a solution?
Do not store the tenant on the controller, as it will not be available to injected services, as you discovered. Create a thin service whose sole responsibility is to determine the tenant identifier. The service can access statics and HttpContext directly. This class doesn’t really need to be unit-testable – its purpose is to isolate the rest of the system so that other classes are testable.
If you want
ITenantContextto be that service, it could look something like:Now your controller can just have a dependency on your repository interface, and your repository implementation (an any other services that care) can depend on
ITenantContext. The controller doesn’t need to know about tenants.