MEF and ASP.NET MVC sample


First things first, don’t consider this sample an official sample. It is just something I’ve created to illustrate some capabilities of MEF when integrated with ASP.NET MVC in the user-level (as opposed to framework level).

Also, if you would try to do this integration yourself, you’ll notice at some point that you’ll need to attach metadata to your controllers, so you can grab the right one on the controller factory. In this sample I provide a custom catalog that is aware of controllers, so it adds the metadata itself saving us the burden. Of course, this adds to complexity..

As MEF targets the extensibility story, this sample is an ASP.NET MVC app that can be “augmented” by new modules. The main app is a shell with almost no functionality. New modules add navigation, controllers, services and consume the services are present on the system.

The first extension module provide adds Wiki support to the main application. The second, a forum module.

Bear in mind that everything is fake. I’m showing how to leverage the extensibilities capabilities of MEF, and not how to design a CMS, Forum or Wiki 🙂

In a real world app a similar extensibility mechanism in a web app would also have to deal with database/versioning issues, content resource (additional css, js, images), and so forth.



You may start by running the app. You should see the following on your browser:


The links above (forum, wiki) were added dynamically by modules loaded.

Where everything starts

The Global.asax.cs holds our bootstrap code:

   1:  protected void Application_Start()
   2:  {
   3:    HostingEnvironment.RegisterVirtualPathProvider(
   4:      new AssemblyResourceVirtualPathProvider());
   6:    RegisterRoutes(RouteTable.Routes);
   8:    var catalog = new CatalogBuilder().
   9:      ForAssembly(typeof(IModuleInstaller).Assembly).
  10:      ForMvcAssembly(Assembly.GetExecutingAssembly()).
  11:      ForMvcAssembliesInDirectory(HttpRuntime.BinDirectory, "*Extension.dll"). 
  12:      Build();
  14:    _container = new CompositionContainer(catalog);
  16:    var modules = _container.GetExportedObjects<IModuleInstaller>();
  17:    var navService = _container.GetExportedObject<NavigationService>();
  19:    InitializeModules(modules, navService);
  21:    ControllerBuilder.Current.SetControllerFactory(
  22:      new MefControllerFactory(_container));
  23:  }

The first line sets up a custom VirtualPathProvider that check assembly resources for content. Nothing new.

Lines 8-12 defines our catalog, which encapsulates the discovery mechanism on MEF. It also provides us opportunities to customize things. In this case, we want to discover things on the Core assembly (line 9), on the executing assembly/web project assembly (line 10), and anything on the web app’s bin folder that ends with Extension.dll (line 11).

A container is created with a reference to the aggregation of all these catalogs. Right after we retrieve all IModuleInstaller implementations available and start all modules, which is to say we give them a chance to change/add URL routes and add navigation information.

Finally, we create a custom IControllerFactory instance and set up ASP.NET MVC to use it (line 21).

The MEF Controller Factory

   1:  public class MefControllerFactory : IControllerFactory
   2:  {
   3:    private const string ControllerExportEntryName = "controllerExport";
   4:    private readonly CompositionContainer _container;
   6:    public MefControllerFactory(CompositionContainer container)
   7:    {
   8:      _container = container;
   9:    }
  11:    public IController CreateController(RequestContext requestContext, string controllerName)
  12:    {
  13:      var controllerExport = _container.GetExports<IController>().
  14:        Where(exp => 
  15:          exp.Metadata.ContainsKey(Constants.ControllerNameMetadataName) &&
  16:          exp.Metadata[Constants.ControllerNameMetadataName].
  17:            ToString().ToLowerInvariant().
  18:            Equals(controllerName.ToLowerInvariant())).
  19:          FirstOrDefault();
  21:      if (controllerExport == null)
  22:      {
  23:        throw new HttpException(404, "Not found");
  24:      }
  26:      requestContext.HttpContext.Items[ControllerExportEntryName] = controllerExport;
  28:      return controllerExport.GetExportedObject();
  29:    }
  31:    public void ReleaseController(IController controller)
  32:    {
  33:      var export = HttpContext.Current.Items[ControllerExportEntryName] as Export<IController>;
  35:      if (export != null)
  36:      {
  37:        _container.ReleaseExport(export);
  38:      }
  39:    }
  40:  }

This implementation, albeit short, shows interests aspects. First, on the CreateController, we get all exports of IController – which is different from getting all _instances_ of IController. Then, we use the metadata associated with those Exports to find the controller we need to get an instance.

We hold this export instance for the duration of this request (HttpContext.Items), so we can use it on ReleaseController. This relies on the assumption that in a request only one controller is instantiated.

The ReleaseController get back that export instance and calls Container.ReleaseExport, which will go over all the object graph, and properly release and dispose NonShared / Disposable instances. If you miss this step you will be in a route to a memory bloat as every controller is non shared and disposable.

The MVC Catalog

This one is a bit more complex, but remember, it is an optional step. I just added it because I’m lazy and didn’t want to add metadata to every controller (it would be a violation of DRY too.)

public class MvcCatalog : ComposablePartCatalog, ICompositionElement
  private readonly Type[] _types;
  private readonly object _locker = new object();
  private IQueryable<ComposablePartDefinition> _parts;
  public MvcCatalog(params Type[] types)
    _types = types;
  // More constructors //
  public override IQueryable<ComposablePartDefinition> Parts
    get { return InternalParts; }
  internal IQueryable<ComposablePartDefinition> InternalParts
      if (_parts == null)
          if (_parts == null)
            var partsCollection = 
              new List<ComposablePartDefinition>();
            foreach(var type in _types)
              var typeCatalog = new TypeCatalog(type);
              var part = typeCatalog.Parts.FirstOrDefault();
              if (part == null) continue;
              if (typeof(IController).IsAssignableFrom(type))
                part = new 
            _parts = partsCollection.AsQueryable();
      return _parts;

What we’re doing here is: for each type discovered – is a MEF part – we also check if it happens to be a controller. If so, we decorate that part to add an additional export. This export has all the extra metadata that we need to query for that controller later on.


As we’re using MEF for extensibility we might just as well use it for typical composition – as long as our requirements are low compared to the use of a full fledge IoC Container.

[Export, PartCreationPolicy(CreationPolicy.NonShared)]
public class ForumController : BasePublicController
  private readonly ForumService _forumService;
  public ForumController(ForumService forumService)
    _forumService = forumService;
  public ActionResult Index()
    ViewData["forums"] = _forumService.GetEnabledForumsRecentActivity();
    return View(ViewRoot + "Index.aspx");

In this controller we import (depend) ForumService, which itself depends on IForumRepository. If you don’t mind the extra noise of attributes, MEF can also cover this aspect of your app – but remember, it wasn’t built to be an IoC Container as the ones out there – more on that in another day.


In the user-level integration MEF plays very well with ASP.NET MVC to enable extensibility on web apps. Of course, this is not the whole story. Like I mentioned, database schema updates/version, making additional content available (js, css, images) and UI Composition are challenging things themselves, but solvable – been there, done that.

With MEF you have one less thing to worry about in this challenging problem space.

Update: Kamil spot the fact that my decorator is leaving out one member, and that essentially makes it ignore the creation policy (which is attached to the part definition, not exports). Sample updated.

Comments (18)

  1. markus says:

    aren’t you the guy who whined and cried about ben not posting samples with best-practices?

  2. Bill Pierce says:

    Looks good.  I would consider augmenting the sample to allow dropping in new extension dlls without restarting the app pool, for the oh snap! factor.

  3. @Bill, thanks Bill. I didnt want to use the FileWatcher as it would increase complexity, but totally doable, yeah.

    @markus, yes I am. What violations of best practices I’m being accused? 🙂

  4. Jeff says:

    Awesome code sample, I am definitley going to roling things out with this.

  5. Torkel says:

    If MEF is not an IoC container why use it as an IoC container?

    What are the pros and cons of using MEF in this instance compared to say Windsor/StructureMap?

    I am very confused to how Microsoft envisions MEF to be used in business apps, i know it is ment as the fundamental plugin framework for MS products.

  6. Hi Torkel,

    MEF isnt a IoC Container like Windsor or StructuredMap, rather it is an IoC Container built for a very particular scenario: open ended extensibility. It can still be used as a standard container as long as you’re OK with its limitations when it is used as such.

    Krzystoff is preparing a blog post on the subject.


  7. Kamil says:

    I have problem?

    1. I created empty constrsutor in HomeController.

    2. I put new breakpoint in this constructor

    3. Many times I refresh page home in webbrowser

    4. I got only 1 hit in breakpoint 🙁 It is ok?

  8. Kamil says:

    In your sample you should add in ControllerPartDefinitionDecorator :-):

    public override IDictionary<string, object> Metadata




       return _inner.Metadata;



  9. Thanks a lot, Kamil. Sample updated 🙂

  10. Andy says:

    I love how simple this module/plugin approach is using MEF. And hope the ASP.NET team bring out some Previews using MEF with MVC in the near future. And using vanilla Import/Export attributes. I think it would be a shame if ASP.NET MVC added too many layers and custom attributes on top of MEF.

    Is there a way to author the embedded Views for the Extensions with designer support in Visual Studio?

  11. Marcel says:

    I created a bootstrapper which allows my IModuleInstaller to add its own view root to my ExtensionWebFormViewEngine.

    This is my Global.asax:

    protected void Application_Start()





    This is my Bootstrapper

    public class ExtensionsBootstrapper


           public static void Attach(Assembly mvcAssembly)


               HostingEnvironment.RegisterVirtualPathProvider(new AssemblyResourceVirtualPathProvider());

               ComposablePartCatalog catalog = new CatalogBuilder()



                   .ForMvcAssembliesInDirectory(HttpRuntime.BinDirectory, Constants.ExtensionsDllSearchPattern).


               var container = new CompositionContainer(catalog);

               Collection<IModuleInstaller> modules = container.GetExportedObjects<IModuleInstaller>();


               ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(container));


           private static void InitializeModules(IEnumerable<IModuleInstaller> installers)


               var viewEngine = new ExtensionWebFormViewEngine();

               foreach (IModuleInstaller installer in installers)









    And my View Engine

    public class ExtensionWebFormViewEngine : WebFormViewEngine


           private readonly IList<string> _viewLocationFormats;

           public ExtensionWebFormViewEngine()


               _viewLocationFormats = new List<string>







               MasterLocationFormats = new[]






           public void AddViewLocation(string viewRoot)


               _viewLocationFormats.Add(viewRoot + "/{1}/{0}.aspx");

               _viewLocationFormats.Add(viewRoot + "/{1}/{0}.ascx");

               _viewLocationFormats.Add(viewRoot + "/Shared/{0}.aspx");

               _viewLocationFormats.Add(viewRoot + "/Shared/{0}.ascx");


           public void Build()


               ViewLocationFormats = _viewLocationFormats.ToArray();

               PartialViewLocationFormats = _viewLocationFormats.ToArray();



  12. felix says:

    Great Article!

    How about the possibility to add this example to mef codeplex site and extend ?

    In this case are possible and how (i am a newbie) add a page to upload my plugin and refresh the catalog?

  13. Jason says:

    This is great for pages.  Would you be able to show how this changes if I wanted to have plugins that were only partial views / i.e. hosting multiple pluggable "widgets" on a single page?

  14. death says:

    I have problem too?

    1. I created Index Action in HomeController.


       [Export, PartCreationPolicy(CreationPolicy.NonShared)]

       public class HomeController : BasePublicController


           public ActionResult Index(string aaa)


    2. I put new breakpoint in this Action

    3. Many times I refresh page home in webbrowser and different aaa value,I got the first enter value;

  15. Greg says:

    I’m having the same issue.  I keep getting the value from the very first call.  Somehow it is getting cached.

  16. luca says:

    If you use strongly typed view your sample not work!

  17. TheoA says:

    Is there new version of this code? I'm using VS2010-.Net4.0 and the code cannot run using debug. It stop at the line:

    "requestContext.HttpContext.Items[ControllerExportEntryName] = controllerExport;" in <<public IController CreateController(RequestContext requestContext, string controllerName){}>>. I can manage to run without debugging but after clicking twice on the menu the code breaks completely. When I loaded the project it was converted to .Net4 by VS. Anything I need to know? thanks.

  18. MikeB says:

    Any chance this could be updated to MVC 3?

Skip to main content