ASP.NET Web API + minimal touch MEF


ASP.NET Web API + minimal touch MEF

this post will offer light touching technique of introducing MEF to ASP.NET Web API.

the motivation for having MEF (or any other IoC container) for Web API
is for dependencies abstraction and testability.

it is also easier to design your API by Contract (mining that you don’t have to think about the actual implementation at design time).

so why minimal touch?

even those other suggestion can be found, most of them involve custom routing. the risk of alter ASP.NET Web API routing, is loose some of the routing benefits like Attribute Routing.

ASP.NET, MEF, Web Api, Controller, IHttpController, IController, Compose

the idea behind this suggestion is to define the MEF container at the Global.asax and intercepting the Web API controller,
then introducing MEF using container.SatisfyImportsOnce(controller).

how to intercept the creation of Web API Controller?

interception of the controller creation is quit easy,
all you have to do is to implement IHttpControllerActivator

Code Snippet
  1. public interface IHttpControllerActivator
  2. {
  3.     IHttpController Create(
  4.         HttpRequestMessage request,
  5.         HttpControllerDescriptor controllerDescriptor,
  6.         Type controllerType);
  7. }

you can also inherit DefaultControllerFactory for normal ASP.NET controller interception.

Code Snippet
  1. class MefControllerFactory :
  2.     DefaultControllerFactory,
  3.     IHttpControllerActivator
  4. {
  6. }

setting the MEF container and replacing the controller factory
Code Snippet
  1. protected void Application_Start()
  2. {
  3.     // …
  6.     var catalog = new DirectoryCatalog(PLUG_IN_FOLDER);
  7.     var container = new CompositionContainer(catalog);
  8.     container.ComposeParts();
  10.     var currentWebApiActivator = GlobalConfiguration.Configuration.Services.GetHttpControllerActivator();
  11.     var mefFactory = new MefControllerFactory(container, currentWebApiActivator);
  12.     ControllerBuilder.Current.SetControllerFactory(mefFactory);
  14.     GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), mefFactory);
  15. }

at the Global.asax within the Application_Start method (after the existing code) add the MEF container (lines 6 – 8) and
replace the default ControllerFactory with MefControllerFactory (lines 10 – 14).

the MefControllerFactory code is shown in the next snippet:

Code Snippet
  1. internal class MefControllerFactory :
  2.     DefaultControllerFactory,
  3.     IHttpControllerActivator
  4. {
  5.     private readonly CompositionContainer _container;
  6.     private readonly IHttpControllerActivator _internalActivator;
  8.     public MefControllerFactory(
  9.         CompositionContainer container,
  10.         IHttpControllerActivator internalActivator)
  11.     {
  12.         _container = container;
  13.         _internalActivator = internalActivator;
  14.     }
  16.     public override IController CreateController(
  17.         RequestContext requestContext,
  18.         string controllerName)
  19.     {
  20.         IController controller =
  21.             base.CreateController(requestContext, controllerName);
  22.         _container.SatisfyImportsOnce(controller); // MEF injection
  23.         return controller;
  24.     }
  26.     public IHttpController Create(
  27.         HttpRequestMessage request,
  28.         HttpControllerDescriptor controllerDescriptor,
  29.         Type controllerType)
  30.     {
  31.         IHttpController controller = _internalActivator.Create(request, controllerDescriptor, controllerType);
  32.         _container.SatisfyImportsOnce(controller); // MEF injection
  33.         return controller;
  34.     }
  35. }

this is a relatively short snippet that inject MEF both for Web API controller (IHttpController) and to the normal ASP.NET controller (IController).


having IoC controller within ASP.NET application can make your dependency injection easy.
this suggestion won’t touch the default ASP.NET routing, therefore you can have both dependency injection and Attribute Routing working together.

Shout it

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>