[英]Construct a connectionString at runtime from the url for ASP.Net MVC Identity 2
I'm working on a multi-tenant web application using ASP.Net C# MVC 5. For reasons not relevant to this question, I want a separate database for each tenant, including the Identity 2.0 part. 我正在使用ASP.Net C#MVC 5开发多租户Web应用程序。出于与该问题无关的原因,我希望为每个租户(包括Identity 2.0部分)建立一个单独的数据库。 Also, I do not want to use the tenant name as hostname before my domain (ie http://tenant.myapp.com
). 另外,我不想在域之前使用租户名称作为主机名(即http://tenant.myapp.com
)。 One obvious solution that's generally easy to implement is to have the tenant name in the MVC route configuration: 通常很容易实现的一个显而易见的解决方案是在MVC路由配置中使用租户名称:
namespace MyApp
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{tenant}/{controller}/{action}/{id}",
defaults: new { tenant = "Demo", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
This works fine, but the approach seems to have one drawback. 这很好用,但是这种方法似乎有一个缺点。 I was hoping to construct a connectionString at runtime, using the tenant from the RouteData.Values and passing that string to my ApplicationDbContext. 我希望在运行时使用RouteData.Values中的租户构造一个connectionString,并将该字符串传递给我的ApplicationDbContext。
I suspect that, during initialization, the Identity framework is initialized as a singleton. 我怀疑在初始化期间,将Identity框架初始化为单例。 From the template MVC code you get the following Startup partial. 从模板MVC代码中,您可以获得以下“启动”部分。
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
...
}
}
The remark states that a single instance is created "per request", but this code looks to be hit only once when the app initializes, not per request. 备注指出,将按“每个请求”创建一个实例,但是该代码看起来仅在应用初始化时被命中一次,而不是每个请求被命中一次。 What I was hoping to do, is do something like this, passing the tenant into the constructor of ApplicationDbContext. 我希望做的是做类似的事情,将租户传递给ApplicationDbContext的构造函数。
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
// Get the tenant from the routeData
string tenant = "YourCompany"; // Switch to something different from the default set during route configuration, for testing purposes.
if (HttpContext.Current.Request.RequestContext.RouteData.Values["tenant"] != null) tenant = HttpContext.Current.Request.RequestContext.RouteData.Values["tenant"].ToString();
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(() => ApplicationDbContext.Create(tenant));
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
...
}
}
But, alas, the HttpContext.Current.Request.RequestContext has no RouteData.Values since we're initiliazing when the code hits and there is no request. 但是,可惜,HttpContext.Current.Request.RequestContext没有RouteData.Values,因为我们在代码命中并且没有请求时进行初始化。 This code always results in a connectionString with 'YourCompany' as tenant. 此代码始终导致一个以“ YourCompany”为租户的connectionString。
I have developed several years ago exactly the same scenario... 几年前,我已经开发出完全相同的场景...
Startup & RouteConfig are executed normally in global.asax/Application_Start , only once per iis-site start. Startup和RouteConfig通常在global.asax / Application_Start中执行,每个iis站点启动仅执行一次。
Try to create and set your DbContext in global.asax/Application_BeginRequest. 尝试在global.asax / Application_BeginRequest中创建并设置您的DbContext 。
And some other hint: perhaps you should have only one DbContext per HttpRequest, by holding it in HttpContext.Current.Items["dbcontext"] for use in child actions or similiar. 还有其他一些提示:通过将其保存在HttpContext.Current.Items [“ dbcontext”]中,以便在子操作或类似操作中使用,每个HttpRequest可能只应具有一个DbContext。
Let me know if you succeed or need more hints 让我知道您是否成功或需要更多提示
Frank 坦率
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.