具有插件和多租户支持的ASP.NET MVC应用程序与单独的AppDomain?

时间:2012-04-26 07:15:13

标签: asp.net-mvc asp.net-mvc-3 serialization mef appdomain

问题

我有一个ASP.NET MVC 3应用程序,其中包含插件/模块架构多租户支持。 MEF用于解析依赖关系并加载可插入部分。

每个模块由控制器,视图和其他对象组成(在体育上它是一个组件)。模块被加载到租户中。

简单配置可能如下所示:

租户1:

  • 模块A,版本1.0(ModuleA.dll)
  • 模块B,版本1.0(ModuleB.dll)

租户2:

  • 模块B,版本1.0(ModuleB.dll)

不同模块和不同版本的Dll分别存储在不同的物理位置。 应用程序在一个AppDomain上运行(默认一个)。

但是,如果我们想在不同租户使用不同模块版本的情况下进行配置,我们会遇到在不同版本中加载相同程序集的问题。这意味着下面的场景不能完全正常工作,因为在从ModuleB解析类型时我们得到了组合不匹配异常(版本1.0和1.5被加载到MEF中,但是只有一个组件已经被组装加载器加载到AppDomain中)。

租户1:

  • 模块A,版本1.0(ModuleA.dll)
  • 模块B,版本1.0(ModuleB.dll)

租户2:

  • 模块A,版本1.5(ModuleB.dll)

解决方案吗

因此我们提出了一个解决方案,即将不同的租户及其模块/程序集加载到单独的AppDomains 中。这意味着我们的示例Tenant1和Tenant2被加载到AppDomain1和AppDomain2中。在ASP.NET MVC管道中,我们连接到控制器工厂,以便选择适当的应用程序域,如下所示:

  • 请求由默认的AppDomain(Web应用程序启动的那个)处理
  • 控制器工厂
    • 从请求中获取Tenant_Id并从适当的AppDomain解析适当的控制器(我们有Tenant_Id-> Tenant-> AppDomain关系)
      • 返回ControllerProxy(它是一个实现IController的代理类,并继承MarshalByRefObject以便能够在不同的App Domians之间传递控制器)
  • 动作祈求者
    • 在控制器代理对象上调用正确的操作,现在执行在底层应用程序domian
    • 中执行
    • 在这里我们碰到了问题,因为动作调用者无法将不可序列化的RequestContext传递给另一个应用程序域(换句话说,controllerProxy.Execute(RequestContext context)会抛出有关序列化的异常)

问题(S):

  • 如何以一种很好的方式在app域之间传递RequestContext(非可序列化对象)?
  • 是否可以连接到管道中的另一个步骤以将执行重定向到基础应用程序域(在控制器工厂之前?)
  • 或者有关此问题的其他解决方案的任何想法?

2 个答案:

答案 0 :(得分:1)

不可能。如果您尝试使用不同的AppDomain,ASP.NET将会回来困扰您。

相反,请使用基于角色的授权来控制不同模块的访问权限。

我刚刚在ASP.NET MVC3中写了一篇关于插件系统的文章:http://blog.gauffin.org/2012/05/griffin-mvccontrib-the-plugin-system/

答案 1 :(得分:0)

这并不能直接回答有关ASP.NET MVC中多个应用程序域的问题。但是,关于其他选项,您可能需要查看托管应用程序框架(a.k.a. System.Addin)。它是.NET Framework的一部分,与MEF类似,它支持动态加载模块。但是,它内置了跨应用程序域拆分这些模块的功能。它可能更适合您的需求。不过,我不确定它与ASP.NET MVC的匹配程度如何。

这个document on MSDN应该让你开始使用MAF。