2016-12-30 99 views
0

我正在使用ASP.NET MVC构建多租户应用程序。现在,注意到一个错误,但是完全随机的间隔,有时来自错误的租户的数据被提取给另一个租户。MVC多租户加载其他租户数据

因此,例如,Tenant1登录,但他们看到来自Tenant2的信息。我使用来自所有租户的相同数据库,但使用了TenantId。

我从启动全球应用程序> Application_AcquireRequestState下面给出:

namespace MultiTenantV1 
{ 
    public class Global : HttpApplication 
    { 
     public static OrganizationGlobal Tenant; 

     void Application_Start(object sender, EventArgs e) 
     { 
      ViewEngines.Engines.Clear(); 
      ViewEngines.Engines.Add(new RazorViewEngine()); 

      AreaRegistration.RegisterAllAreas(); 
      FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
      RouteConfig.RegisterRoutes(RouteTable.Routes); 
      BundleConfig.RegisterBundles(BundleTable.Bundles); 
      UnityWebActivator.Start(); 
     } 

     void Application_AcquireRequestState(object sender, EventArgs e) 
     { 
      // boot application 
      HttpApplication app = (HttpApplication)sender; 
      HttpContext context = app.Context; 

      // dependency runner 
      Tenant = new Tenant().Fetch(context.Request.Url); 

      // third party api calls 
      var session = HttpContext.Current.Session; 
      if (session != null) 
      { 
       if (string.IsNullOrEmpty(Session["CountryCode"] as string)) 
       { 
        string isDevelopmentMode = ConfigurationManager.AppSettings["developmentmode"]; 
        if (isDevelopmentMode == "false") 
        { 
         // api call to get country 
        } 
        else 
        { 
         // defaults 
        } 
       } 

       Tenant.CountryCode = Session["CountryCode"].ToString(); 
      } 
     } 
    } 
} 

现在,在整个应用程序我用“租客”对象为出发点,并以此来查询数据库,进行进一步的数据。我注意到,有时租户会看到另一个租户名称(不确定其他数据是否也以相同的方式显示)。

我正在基于HttpContext.Request.Url初始化'Tenant'。因此无法加载其他租户数据。

任何人都可以在上面的代码中看到任何东西,或者在我使用HttpContext.Request.Url时可能导致错误的租户被提取用于任何特定的请求吗?

回答

1

每个请求都会覆盖静态Tenant对象,因此在并发请求中将使用错误的租户。

关键是要存储每个请求的租户,例如在HttpContext.Current。我通常使用租赁解析器,其中包含这样的代码:

public string CurrentId { 
     get { 
      return (string)HttpContext.Current.Items["CurrentTenantId"]; 
     } 
     set { 
      string val = value != null ? value.ToLower() : null; 
      if (!HttpContext.Current.Items.Contains("CurrentTenantId")) { 
       HttpContext.Current.Items.Add("CurrentTenantId", val); 
      } else { 
       HttpContext.Current.Items["CurrentTenantId"] = val; 
      } 
     } 
    } 

Application_AcquireRequestState我设置CurrentId根据网址。

然后通过获得CurrentId,然后在需要了解租户的类中使用tenancyresolver。

+1

“关键是存储每个请求的租户”,这足以解决问题。谢谢@ jeroen K –

+0

@jeroen K,你在哪里放置CurrentId属性,以便它可以在控制器中访问? – Picflight

+0

@Picflight我有一个名为TenancyResolver(具有CurrentId属性)的类,我在控制器中使用它。它通过DI框架(simpleinjector)注入,在那里它被注册为每个请求单例。 –