Monday, February 27, 2012

ASP.NET MVC 3: Call Controller from external assembly

I've recently encountered a task to have pluggable controllers so that you could change web application behavior without source code recompilation. The idea was to update an assembly in the /Bin folder, possibly put/update some views under web application root folder and get new behavior in place.

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"}
);
}

1 comment:

  1. Hi there.
    One question. How use DLL wihout placing in Bin directory?
    Let say, we have

    WWWRoot
    -Bin
    -ExternalsDlls
    -Views
    -Shared
    ....

    Can we use libraries from ExternalsDlls ?

    ReplyDelete