Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC application with plugin and multitenancy support with separate AppDomains?

Problem

I have an ASP.NET MVC 3 application with the plug-in/module architecture and multi-tenancy support. MEF is used to resolve dependencies and load pluggable parts.

Each module consists of controllers, views, and other objects (phisically it's one assembly). Modules are loaded into tenants.

The simple configuration might look like this:

Tenant 1:

  • Module A, version 1.0 (ModuleA.dll)
  • Module B, version 1.0 (ModuleB.dll)

Tenant 2:

  • Module B, version 1.0 (ModuleB.dll)

Dll's for different modules and different versions are stored separately in different physical locations. And application is running on one AppDomain (default one).

However, if we would like to do configuration where different tenants use different module versions, we encounter problem with loading the same assembly in different version. Which means that scenario below is not fully working because during resolving types from ModuleB we got composition mismatch exception (version 1.0 and 1.5 was loaded into MEF but only one assembly has been loaded into AppDomain by assembly loader).

Tenant 1:

  • Module A, version 1.0 (ModuleA.dll)
  • Module B, version 1.0 (ModuleB.dll)

Tenant 2:

  • Module A, version 1.5 (ModuleB.dll)

Solution?

So we came up with one solution, which is to load different tenants and theirs modules/assemblies into separate AppDomains. Meaning that from our example Tenant1 and Tenant2 are loaded into AppDomain1 and AppDomain2. In ASP.NET MVC pipeline we hooked up into controller factory in order to choose proper app domain, which would look like this:

  • Request is handled by default AppDomain (the one that web application started)
  • Controller factory
    • Takes Tenant_Id from the request and resolves proper controller from proper AppDomain (we have Tenant_Id->Tenant->AppDomain relation)
      • Returns ControllerProxy (which is a proxy class that implements IController and inherits MarshalByRefObject to be able to pass controller between different App Domians)
  • Action Invoker
    • Proper action is invoked on controller proxy object and right now execution takes place in underlying app domian
    • And here we bumped into problem because action invoker is not able to pass not serializable RequestContext to another app domain (in other words controllerProxy.Execute(RequestContext context) is throwing exception about serialization)

Question(s):

  • How to pass RequestContext (non serializable object) between app domains in a nice way?
  • Is it possible to hook up into another step in the pipeline to redirect execution to underlying app domain (before controller factory?)
  • Or any ideas about another solution for this problem?
like image 505
untoldex Avatar asked Nov 14 '22 06:11

untoldex


1 Answers

Not possible. ASP.NET will come back and haunt you if you try to use different AppDomains.

Instead, use the role based authorization to control access for the different modules.

I've just written an article about plugin systems in ASP.NET MVC3: http://blog.gauffin.org/2012/05/griffin-mvccontrib-the-plugin-system/

like image 114
jgauffin Avatar answered Dec 16 '22 07:12

jgauffin