I know that is a whole host of acronyms in the title, so let me explain. Recently it came to my attention at my day job that I was going to have to support two versions of our API simultaneously. This information came as no surprise to me, but unfortunately it wasn’t something I originally planned for when carefully laying out the URL patterns for the REST API.
Since I was going to have to yank the current code apart to support the new API in parallel with the previous API, I decided to do things right and put a wish list in place for what I wanted to accomplish with the next version of the API:
- Ability to support /vN/ (ex. /v1/ and /v2/) in the URL so that the URL looks like http://mysite/v1/api/method
- Ability to deploy versions of API in separate DLL’s, so that the URL is versioned similar to the libraries.
As I was searching for a non-hacky way to accomplish this I stumbled across using MEF for creating a MEF based MVC Controller Factory. This was a great find because it provided me everything I was looking for. It allowed me to add meta data to each controller, so that I could specify the version that the controller was (i.e. “v1” or “v2” etc.).
To get started the first thing I needed to do was setup the MEF container. On the web it is a little more complicated, because of the stateless nature of a web application. So I created a MefHttpApplication base to replace the standard HttpApplication in the Global.asax file. Here is how it should look:
public class MvcApplication : MefHttpApplication
Next we need to change the default route to support versioning:
routes.MapRoute(
"Default",
"{version}/{controller}/{action}",
new { version = "v1" }
);
After that is completed the next step is to actually register our new Controller Factory with MVC. This is a very important step because it is the glue between MVC and MEF, and it is what brings the two frameworks together.
public void RegisterControllerFactory(ControllerBuilder controllerBuilder)
{
controllerBuilder.SetControllerFactory(new MefControllerFactory(ContainerManager));
}
protected override void Application_Start()
{
base.Application_Start();
RegisterControllerFactory(ControllerBuilder.Current);
}
Before we go on to create our MefControllerFactory, it is probably best to show how the meta-data attributes for MEF are applied to the controllers, it will make understanding how the MefControllerFactory works easier. I am not going to go in to much detail, because there are much more in-depth and better explanations than I can give on how these work, I am only going to tell you the code that I am showing you does work:
[Export(typeof(IController))] [ExportMetadata(Constants.MetaControllerName, "Billing")] [ExportMetadata(Constants.MetaApiVersion, "v1")] [ExportMetadata(Constants.MetaScopeMode, WebScopeMode.Request)] public class BillingController : Controller
The next thing we need to create is the MefControllerFactory.
I am just going to post the parts below that I want to talk about and that are relevant to this blog post, but I have posted the full file online for your viewing pleasure.
With the MefControllerFactory we want to find the controller out of the MEF container that both matches the version and the controller name that is being requested as part of the route. To do this we can use LINQ:
controllers = controllers
.Where(exp =>
exp.Metadata.ContainsKey(Constants.MetaControllerName)
&& String.Equals(exp.Metadata[Constants.MetaControllerName].ToString(), controllerName, StringComparison.InvariantCultureIgnoreCase))
.Where(exp =>
exp.Metadata.ContainsKey(Constants.MetaControllerName)
&& String.Equals(exp.Metadata[Constants.MetaApiVersion].ToString(), version, StringComparison.InvariantCultureIgnoreCase));
The above LINQ query queries for all controllers in the MEF container that have both the same controller name and same API version as was requested by the route. The important parts to notice about the above query is the names Constants.MetaControllerName and Constants.MetaApiVersion they are the same constants that are used in the above ExportMetadata attributes on the controller.
The last part to getting this working is merely a preference of mine. But when I create a versioned URL schema like this I like to have separate projects for each version, so I break out the Controller classes in to their own project, so that I have a library of just controllers. I do this so that when I want to create another version of the API say going from v1 to v2 or v2 to v3, I just need to take a copy of my entire controller project and update the versions and start working from that point moving forward.
Hope this helps somebody, because versioning your web API is a complex process, because if you don’t want to be a totally jerk to your users you have to support both interfaces for a period of time to give the users a chance to move from the current version to the next. My goal with the above code was to make supporting both versions easy.
MEF, MVC

Well, it hasn’t really helped me. But it was a well explained and educational blog post that may turn out to be useful in the future.
Thanks for taking the time to write it.
Just a thought (simply because i have zero MEF experience)…
i would do as you’ve done, with a project per version, but the projects would contain only the services for the given version. I would register the services in the IOC container with a name reflecting the version.
There would then only need to be a single controller per API, since services can be pulled from the container by name.
MEF has many of the abilities of an IoC, but it has a better definition system than most of the IoC out there because it is attribution based, not configuration based.
Lets first start by why we want to version an API. You want to version API’s if a breaking change is going to occur either between the input parameters or the output response.
The problem, IMO, with a single controller per API is that it doesn’t allow you to change the parameters, without jumping through a ton of hoops by reimplementing much of what MVC already does. You could definitely take that approach by passing in parameters from the GET or POST and pass them in to the service to handle the request. But at that point you are just reimplementing MVC for no purpose other than to satisfy a need to use IoC, which is a poor use of IoC.
Plus you encounter many upgrade hurdles when you want add a new controller actions to v2 of your API that didn’t exist in v1. So now you have to make two different versions of your interface for the service, and you are back to square one of not being able to version your API, since IoC relies on common interfaces. But if you still really wanted to use IoC, I guess you could reimplement the Routing system too, so that you can pass in paths to your common interface.
But at this point you have reimplemented the parameter checking of the controller actions, and the routing system. So you might as well just give up on MVC and use a straight handler.
All of this was just to show you the problems with using a service based approach with IoC. The better approach with IoC would be to just create a controller factory like the one above, and customize it to your own needs based on your usage of IoC, the same I did with the MEF example.
I am currently working on moving an existing request/response API that is using a more traditional web method approach into a cleaner RESTful API. Versioning, loose coupling, maintainability and extensibility are my primary goal for this iteration of the project – I have been toying with the idea of using MEF to achieve these goals but had not thought of using MVC. My implementation was a custom handler so I am extremely interested in your solution stated above. How would I go about getting more details about your project?
Robert, you can find the full controller factory here. https://gist.github.com/571188 and the HttpApplication here https://github.com/managedfusion/managedfusion-web/blob/master/src/Composition/MefHttpApplication.cs
You can also find the compiled library of ManagedFusion.Web by pulling it down from NuGet which is the easy and recommended way of getting started with it.
Outstanding!!
Thanks you so much for the speedy response.