MVC does not find the controller

In a previous post I talked about using MVC’s controller injection to drop in DLLs that contain controller classes. It allows for a nice separation leading onto creating a composite UI. I was happily using this mechanism when it just refused to load a controller from an additional DLL. I still do not understand why it doesn’t work but my workaround is to override the ControllerFactory. Here is a quick example of this, please note I’ve hardcoded the condition for the sake of this example.

protected void Application_Start()         
  ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
public class MyControllerFactory : System.Web.Mvc.DefaultControllerFactory
protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName)         
  if (controllerName == "Library")
    Type reflib = Type.GetType("LibraryUI.Library,LibraryUI");
    return reflib;                              
  return base.GetControllerType(requestContext, controllerName);         

Note: setcontrollerfactory is a bit old school, should be using the IoC of choice…I’ll need to look into a bit more, but for now this works

Poor mans composite UI or separating out controllers in MVC3

I was looking to create a simple composite UI style application in Microsoft MVC3. What I want is a host MVC application that will compose its UI from other Controllers and Views packaged in other DLLs. The concept comes from autonomous components and SOA where a service owns not only its traditional business services but all the data and almost-all of the UI.

I thought I would be overriding controller builders, adding configuration, etc, etc, but actually this “poor-mans” variant is very easy. Here are the steps I followed;

  1. Create your Host MVC3 web application (Host.proj), for the sake of this example choose the Internet application so you get the default HomeController
  2. Create your satellite MVC3 controller by creating a standard class library project, called Satellite.proj
  3. Add a reference in Satellite to System.Web.Mvc
  4. Create a controller for your satellite, say MyController. Add an ActionResult such as;
    public class MyController : Controller 
      public ActionResult MyInformation() 
        return View("MyInformation2");
  6. Create the View folders for your controller in the Satellite project, e.g. Views\My\
  7. Now for linking them together. I just added a project reference from Host to Satellite in order to grab the DLL. The Views are slightly harder, I used a post build event in the Satellite such as; xcopy “$(ProjectDir)Views” “$(SolutionDir)Host\Views” /E /R /Y
  8. That’s it. Just add some code to use the controller, such as placing the following in the index view;
  9. @Html.Action("MyInformation","My")

    Edit: Note you get errors complaining that ‘there is no build provider registered for the extension’ you need add a dummy web.config to the project, follow these instructions;
    Using Razor in a class library