简体   繁体   中英

Injecting multi-tenant repositories with StructureMap in ASP.NET MVC

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 ITenantContext to be that service, it could look something like:

public class TenantContext : ITenantContext
{
    public string GetTenant()
    {
        var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current));
        return routeData.GetRequiredString("tenant");
    }
}

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.

@FreshCode, I don´t know if you have a dependency on the repository directly in your controller or if your controller has a dependency on a service, which in turns, has a dependency on the repository. However, when the controller is instantiated by structuremap, the service or repository should be already instantiated. We determine the tenant on the Begin_Request and inject the instantiated context into structuremap, with the Inject method. That executes before the controller factory does, so when the controller is instantiated all it´s dependencies have already been created.

Regards.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM