C# 在运行时从ASP.Net MVC标识2的url构造connectionString

C# 在运行时从ASP.Net MVC标识2的url构造connectionString,c#,asp.net-mvc-5,asp.net-identity,C#,Asp.net Mvc 5,Asp.net Identity,我正在使用ASP.NETC#MVC5开发一个多租户web应用程序。出于与此问题无关的原因,我希望每个租户都有一个单独的数据库,包括Identity 2.0部分。此外,我不想在我的域之前使用租户名称作为主机名(即http://tenant.myapp.com)。 通常易于实现的一个显而易见的解决方案是在MVC路由配置中使用租户名称: namespace MyApp { public class RouteConfig { public static void Reg

我正在使用ASP.NETC#MVC5开发一个多租户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 }
            );
        }
    }
}
这很好,但这种方法似乎有一个缺点。我希望在运行时使用RouteData.Values中的租户构造一个connectionString,并将该字符串传递给我的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);

        ...
    }
}
我怀疑,在初始化过程中,Identity框架被初始化为单例。从模板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);

        ...
    }
}
公共部分类启动
{
public void ConfigureAuth(IAppBuilder应用程序)
{
//将数据库上下文、用户管理器和登录管理器配置为每个请求使用一个实例
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext(ApplicationUserManager.Create);
app.CreatePerOwinContext(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);

        ...
    }
}
公共部分类启动
{
public void ConfigureAuth(IAppBuilder应用程序)
{
//从routeData找到租户
string tenant=“YourCompany”;//在路由配置过程中切换到与默认设置不同的内容,以便进行测试。
if(HttpContext.Current.Request.RequestContext.RouteData.Values[“tenant”]!=null)tenant=HttpContext.Current.Request.RequestContext.RouteData.Values[“tenant”].ToString();
//将数据库上下文、用户管理器和登录管理器配置为每个请求使用一个实例
app.CreatePerOwinContext(()=>ApplicationDbContext.Create(租户));
app.CreatePerOwinContext(ApplicationUserManager.Create);
app.CreatePerOwinContext(ApplicationSignInManager.Create);
...
}
}

但是,遗憾的是,HttpContext.Current.Request.RequestContext没有RoutedData.Value,因为我们在初始化代码时没有请求。这段代码总是导致以“YourCompany”作为租户的连接字符串。

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

Startup&RouteConfig在全局中正常执行。asax/Application\u Start,每次iis站点启动仅执行一次

尝试在global.asax/Application\u BeginRequest中创建并设置DbContext。

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

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


弗兰克

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

Startup&RouteConfig在全局中正常执行。asax/Application\u Start,每次iis站点启动仅执行一次

尝试在global.asax/Application\u BeginRequest中创建并设置DbContext。

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

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


Frank

那么您希望在运行时动态决定连接字符串吗?那么您希望在运行时动态决定连接字符串吗?我认为您指向global.asax/Application\u BeginRequest的指针方向正确。我应该能够在那里做的是为OWIN更改de DbContext。每个请求都可以这样做吗?我认为您指向global.asax/Application_BeginRequest的指针方向正确。我应该能够在那里做的是为OWIN更改de DbContext。每个请求都可以这样做吗?