Search code examples
asp.net-mvc-3mef

ASP.NET MVC 3.0 + Microsoft.Web.Mvc 3.0 + MEF compatibility


When i have an reference to Microsoft.Web.Mvc.dll in my ASP.NET MVC 3.0 project i am getting an error when i am building DirecotryCatalog in my CustomDependencyResolver.

string path = HostingEnvironment.MapPath("~/bin");
 var container = new DirectoryCatalog(path); 

Then i looked at container.Parts.Results View.LoadedExeptions and it is saying:

+[0]{"Method 'GetControllerSessionBehavior' in type 'Microsoft.Web.Mvc.MvcDynamicSessionControllerFactory' from assembly 'Microsoft.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.":"Microsoft.Web.Mvc.MvcDynamicSessionControllerFactory"} System.Exception {System.TypeLoadException}

+[1]{"Method 'GetControllerSessionBehavior' in type 'Microsoft.Web.Mvc.Resources.ResourceControllerFactory' from assembly 'Microsoft.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.":"Microsoft.Web.Mvc.Resources.ResourceControllerFactory"} System.Exception {System.TypeLoadException}

Just for test i removed reference to Microsoft.Web.Mvc.dll(physically removing it from bin direcotry) and then everything just fine. Looks like Microsoft.Web.Mvc.dll couldn't be loaded.

Is there any work around?

I found similar issue here http://forums.asp.net/t/1622399.aspx?MVC+3+RC.+Where+is+the+Futures+Assembly%3F the answer saying that MVC 3 Beta Futures + MVC 3 RC Runtime = are incompatible. But i am using both RTM versions:

Microsoft.Web.Mvc Runtime version v4.0.30319, Version 3.0.0.0 (downloaded from here http://mvccontrib.codeplex.com/releases/view/59313)

System.Web.Mvc Runtime version v4.0.30319, Version 3.0.0.0

UPDATED:

As Darin Dimitrov menthioned in his answer i need to exclude System.Web.Mvc from scanning process. Here is the way how to do that:

public class SafeDirectoryCatalog : ComposablePartCatalog
{
    private readonly AggregateCatalog _catalog;

    public SafeDirectoryCatalog(string directory)
    {
        var files = Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories);

        _catalog = new AggregateCatalog();

        foreach (var file in files)
        {
            try
            {
                var asmCat = new AssemblyCatalog(file);

                //Force MEF to load the plugin and figure out if there are any exports
                // good assemblies will not throw the RTLE exception and can be added to the catalog
                if (asmCat.Parts.ToList().Count > 0)
                    _catalog.Catalogs.Add(asmCat);
            }
            catch (ReflectionTypeLoadException)
            {
            }
        }
    }
    public override IQueryable<ComposablePartDefinition> Parts
    {
        get { return _catalog.Parts; }
    }
}

Solution

  • MEF chokes because it is scanning all assemblies in the bin folder which contain interfaces and classes and the MvcDynamicSessionControllerFactory class which implements IControllerFactory happens to be sealed. So the only solution I see here is to exclude the Microsoft.Web.Mvc assembly from this scanning process. I am not familiar with MEF but in StructureMap which has the same problem you could exclude types.