I’ve been putting together a pluggable MVC framework using MEF in C# 4.0.
MEF was chosen over other solutions such as Portable Areas as it allows all plugins to be composed together as a single site at runtime without the assemblies needing to reference each other.
After scouring the web for ideas, I stumbled upon Maarten Balliauw’s excellent posts for accomplishing this task:
ASP.NET MVC and the Managed Extensibility Framework (MEF)
Revised: ASP.NET MVC and the Managed Extensibility Framework (MEF)
It seems that there are issues using strongly-typed views in this scenario, though, as the types referenced in the views are not found or loaded at runtime. Maarten’s solution is to copy the plugins into the main website’s bin directory so that they can be discovered at runtime.
This can also be solved in another (more elegant?) way by using AssemblyResolve to tell the framework where to load a type from when it is requested by the views.
In this way, your plugin directory needn’t be a sub-directory of the website’s bin folder.
Unfortunately, this doesn’t work without a bit of fettling and the key to getting it working is to give the framework a hint to the assembly the type is in. This in turn forces the AssemblyResolve event to fire. To accomplish this, use an assembly directive at the top of your strongly-typed views as follows:
<%@ Assembly Name="Web.Plugins.Controls" %>
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Web.Plugins.Controls.Models.MenuModel>" %>
An example of using AssemblyResolve by David Morton can be found here:
Assembly Resolution with AppDomain.AssemblyResolve
Which can be bent to our will:
public void Initialize()
// Add assembly handler for strongly-typed view models
AppDomain.CurrentDomain.AssemblyResolve += PluginAssemblyResolve;
private Assembly PluginAssemblyResolve(object sender, ResolveEventArgs resolveArgs)
Assembly currentAssemblies = AppDomain.CurrentDomain.GetAssemblies();
// Check we don't already have the assembly loaded
foreach (Assembly assembly in currentAssemblies)
if (assembly.FullName == resolveArgs.Name || assembly.GetName().Name == resolveArgs.Name)
// Load from directory
return LoadAssemblyFromPath(resolveArgs.Name, _fullPluginPath);
private static Assembly LoadAssemblyFromPath(string assemblyName, string directoryPath)
foreach (string file in Directory.GetFiles(directoryPath))
if (TryLoadAssemblyFromFile(file, assemblyName, out assembly))
private static bool TryLoadAssemblyFromFile(string file, string assemblyName, out Assembly assembly)
// Convert the filename into an absolute file name for
// use with LoadFile.
file = new FileInfo(file).FullName;
if (AssemblyName.GetAssemblyName(file).Name == assemblyName)
assembly = Assembly.LoadFile(file);
assembly = null;
This is an example framework based on Maarten’s using this method. It requires C# 4.0 and Visual Studio 2010 and it is recommended to run without debugging to avoid slow execution when view caching is disabled (Don’t Panic).
The sample framework includes the following functionality:
- Embedded resources handling
- Plugin registration priority for selecting controllers and views
- Menu and menu item registration with ordering
- Sample authentication module
- Automatic site.master resolving
The resource handling is borrowed from the Spark view engine sample modules:
This should serve as a nice starting point for your next MVC pluggable project