在运行时从ASP.Net MVC Identity 2的url构造一个connectionString



我正在使用ASP.Net C#MVC 5开发一个多租户web应用程序。出于与此问题无关的原因,我希望每个租户都有一个单独的数据库,包括Identity 2.0部分。此外,我不想在我的域(即http://tenant.myapp.com)之前使用租户名称作为主机名。一个通常很容易实现的明显解决方案是在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 }
            );
        }
    }
}

这很好,但这种方法似乎有一个缺点。我希望在运行时构建一个connectionString,使用RouteData.Values中的租户,并将该字符串传递给我的ApplicationDbContext。

我怀疑,在初始化过程中,Identity框架被初始化为单例。从模板MVC代码中,您可以获得以下Startup部分。

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);
        ...
    }
}

备注指出,"每个请求"都会创建一个实例,但当应用程序初始化时,这段代码似乎只命中一次,而不是每个请求。我希望做的是这样做,将租户传递到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);
        ...
    }
}

但是,遗憾的是,HttpContext.Current.RequestContext没有RouteData.Values,因为我们在代码命中且没有请求时进行初始化。此代码总是生成一个以"YourCompany"为租户的connectionString。

我几年前开发了完全相同的场景。。。

启动&RouteConfig在global.asax/Application_Start中正常执行,每次iis站点启动仅执行一次。

尝试在global.asax/Application_BeginRequest中创建并设置DbContext。

还有一些其他提示:也许每个HttpRequest应该只有一个DbContext,将其保存在HttpContext.Current.Items["DbContext"]中,以便在子操作或类似操作中使用。

如果你成功或需要更多提示,请告诉我

Frank

相关内容

  • 没有找到相关文章