As it turned out ASP.NET MVC 3 standard controller factory is pretty smart and may automatically search for controllers in all assemblies under /Bin folders (under web app root) and load them - for the simple case described there's no need to use any IoC container, MEF or other 3rd parties.
In order to obtain a working external assembly controller you have to:
- Create a class library and reference System.Web.Mvc
- Add controller class and fill in logic
- Put the outpy DLL to web application /Bin folder. Application will be restarted. While debugging you may reference the class library with the controller to get it automatically copied to /Bin folder.
- Put the view file(s) for action(s) defined in the controller to web application folder.
Views for the actions within external controller will be resolved according to standard ASP.NET MVC rules and searched under /Views folder (until you start defining full view paths in action methods).
In case you have 2 DLL's in the been folder which contain controller classes with same names then default routes will fail and upon request to action within controller name non unique an error will occur. In order to resolve conflicts you need to amend route table in global.asax and explicitly pass namespaces to be used for controller classes resolution (assuming we have same controllers in ExternalAssembly.Controllers and ExternalAssembly2.Controllers the first will take precedence):
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Default", action = "Index", id = UrlParameter.Optional },
new[] {"ExternalAssembly.Controllers"}
);
}