views:

39

answers:

1

I'm trying to determine if MEF is a the proper direction our application framework should be taking. From my reading of MEF, our framework doesn't seem to 'exactly' fit in, but I'll see if any experts can guide me.

Our framework allows us to have one core website and dependent assemblies deployed to one place (and fixes or features are propogated to all clients), then we have client websites that kind of 'merge' into the core website and extend it where needed.

Now in IIS, each client site is its own application running in its own AppDomain. However, every application has the same physical path pointing at the 'core website'.

So our file structure is...

  • /CoreSite
    • /bin (containing core site and dependency dlls)
    • /[Core site folders] (e.g. Models, Views, Controlers, Content, etc.)
    • /Clients
      • /_Assemblies (containing all the client assemblies - 100s of clients)
      • /Client1
        • /[Client site folders] (e.g. Models, Views, Controllers, etc.)
      • /Client2
        • /[Client site folders] (e.g. Models, Views, Controllers, etc.)
      • /ClientN

So as you may have guessed, assembly loading is our issue. We didn't want to put all the client assemblies into the root /bin folder for a couple reasons. First we didn't want each client site to load every other clients assembly. Secondly, we didn't want every site's AppDomain to be recycled simply because another client's assembly was updated in the /bin folder.

To make this work in asp.net 1.1, we followed http://www.hanselman.com/blog/MovingTheCodeBehindAssembliesDLLsToADifferentFolderThanBINWithASPNET11.aspx and added the <probing privatePath="bin;Clients/_Assemblies"/> element in the web.config along with the <%@ Assembly Name="ClientN" %> directive in each view in the client sites. The only other problem we had to overcome was updating the client assemblies, but asp.net 1.1 would lock the assemblies in /Clients/_Assemblies directory. We simply added:

if ( Directory.Exists( assembliesDir ) && AppDomain.CurrentDomain.SetupInformation.ShadowCopyDirectories.IndexOf( assembliesDir ) < 0 )
{
    AppDomain.CurrentDomain.SetShadowCopyPath( AppDomain.CurrentDomain.SetupInformation.ShadowCopyDirectories + ";" + assembliesDir );
}

And viola, everything seemed to work like a charm. Unfortunately in asp.net 4.0, AppDomain.CurrentDomain.SetShadowCopyPath() has been deprecated. So we've been messing around with trying to load assemblies ourself from a byte array, attempted to use AssemblyResolve event, have messed around in the [assembly: PreApplicationStartMethod( typeof( MvcApplication ), "PreApplicationStart" )], have tried using System.Compilation.BuildManager.AddReferencedAssembly to no avail.

We either get: - no assembly loaded - too many assemblies loaded, or - the assembly gets loaded but when a view is rendering and encounters a <Import/> directive where the namespace should have located from <%@ Assembly Name="ClientN" %> simply fails.

So I'm asking for any suggestions using any mechanism and/or advice on whether MEF is the way to go. My 1000 foot view is that MEF is geared more towards 1 application (and or website) that has several components plug into it. I'm hesitant to start a major code refactor (it seems) because in our situation, we only ever have one component plug into it at a time per application/appdomain. It also seems to do a lot more than what we need it to (simply get the assembly loaded and have asp.net recognize it...then all our code will work).

Any advice is greatly appreciated.

A: 

It looks like what you need to do is figure out how to enable shadow copying for all of the folders you have assemblies in. The reason the method you were using is deprecated is because you really need to set this before the AppDomain is created. So my guess is there's probably something you need to set up in your web.config to enable this.

MEF might or might not be a good fit for your application, but it won't solve the shadow copying issue.

Daniel Plaisted