我正在开发一个多租户应用程序。目前我想要实现的是获得每个租户唯一的HttpContext实例。
RouteData.Values["tenant"]
以下是一些简化代码,因此请不要关注架构:
路线网址模式: {tenant}/{controller}/{action}/{id}
的Global.asax.cs:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
// Delegates for BuildSessionFactory and GetSession are declared under Application_Start()
// Registers SessionFactory to be Singletone per Tenant
builder.Register(BuildSessionFactory).As<ISessionFactory>().InstancePerTenant();
builder.Register(GetSession).As<ISession>().InstancePerRequest();
// This is the module responsible for mapping HttpContextBase to HttpContextWrapper and other mvc specific abastractions
builder.RegisterModule(new AutofacWebTypesModule());
var container = builder.Build();
// Build multitenant container
var mtc = new MultitenantContainer(new RouteDataTenantIdentificationStrategy("tenant"), container);
DependencyResolver.SetResolver(new AutofacDependencyResolver(mtc));
}
private ISessionFactory BuildSessionFactory(IComponentContext context)
{
return new NHibernateConfiguration().BuildConfiguration().BuildSessionFactory();
}
private ISession GetSession(IComponentContext context)
{
return context.Resolve<ISessionFactory>().OpenSession();
}
HomeController 示例:
public class HomeController : Controller
{
private readonly ISession _session;
private readonly HttpContextBase _context;
public HomeController(ISession session, HttpContextBase context)
{
_session = session;
_context = context;
}
public ActionResult Index()
{
// Setting up HttpContext.Session["testSessionKey"] only for tenant1
if (_context.Request.RequestContext.RouteData.Values["tenant"] as string == "tenant1")
{
_context.Session.Add("testSessionKey","Some value specific to tenant1 only");
}
using (var transaction = _session.BeginTransaction(IsolationLevel.ReadCommitted))
{
var tenants = _session.Query<Tenant>().ToList();
transaction.Commit();
return View(tenants);
}
}
}
备注:上面的代码忽略了租户的真实存在。它只是根据RouteDataTenantIdentificationStrategy("tenant")
类定义来满足依赖关系(通过RouteData识别没有例外)。
/tenant1/Home/Index
已添加HttpContext.Session['testSessionKey']
。/otherTenant/Home/Index
之类的内容时HttpContext.Session['testSessionKey']
仍在那里。如何使用 Autofac 的依赖注入实现每个租户的唯一HttpContext?
如何获得比HttpContext更多的东西?让我们说一个包含租户的HttpContext
的WorkContext如果有什么不清楚,请询问,我会提供必要的说明。谢谢!
答案 0 :(得分:2)
如果将上下文值的自定义推送到HttpContextBase
的注册,则可以执行此操作。而不是使用AutofacWebTypesModule
,请使用您自己的注册:
builder.Register(c =>
{
var httpContext = new HttpContextWrapper(HttpContext.Current);
var strategy = c.Resolve<ITenantIdentificationStrategy>();
// Update the context here
return httpContext;
}).As<HttpContextBase>()
.InstancePerRequest();
这意味着您还应该在容器中注册您的租户ID策略,但这很容易。
(很抱歉这个简短的片段;我正在手机上旅行。)