Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to register a Controller into ASP.NET MVC when the controller class is in a different assembly?

My goal is to modify asp.net mvc's controller registery so that I can create controllers and views in a separate (child) assembly, and just copy the View files and the DLLs to the host MVC application and the new controllers are effectively "Plugged In" to the host app.

Obviously, I will need some sort of IoC pattern, but I'm at a loss.

My thought was to have a child assembly with system.web.mvc referenced and then to just start building controller classes that inherited from Controller:

Separate Assembly:

using System.Web; using System.Web.Mvc;  namespace ChildApp {     public class ChildController : Controller     {         ActionResult Index()         {             return View();         }     } } 

Yay all fine and dandy. But then I looked into modifying the host application's Controller registry to load my new child controller at runtime, and I got confused. Perhaps because I need a deeper understanding of C#.

Anyway, I thought I needed to create a CustomControllerFactory class. So I started writing a class that would override the GetControllerInstance() method. As I was typing, intellisence popped this up:

Host MVC Application:

public class CustomControllerFactory : DefaultControllerFactory  {     protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)     {         return base.GetControllerInstance(requestContext, controllerType);     } } 

Now, at this point I'm at a loss. I don't know what that does. Originally, I was going to write a "Controller Loader" class like a Service Locator like this:

Host MVC Application:

public class ControllerLoader {     public static IList<IController> Load(string folder)     {         IList<IController> controllers = new List<IController>();          // Get files in folder         string[] files = Directory.GetFiles(folder, "*.plug.dll");         foreach(string file in files)         {             Assembly assembly = Assembly.LoadFile(file);             var types = assembly.GetExportedTypes();             foreach (Type type in types)             {                 if (type.GetInterfaces().Contains(typeof(IController)))                 {                     object instance = Activator.CreateInstance(type);                     controllers.Add(instance as IController);                 }             }         }         return controllers;     } } 

And then I was planning on using my list of controllers to register them in the controller factory. But ... how? I feel like I'm on the edge of figuring it out. I guess it all bois down to this question: How do I hook into return base.GetControllerInstance(requestContext, controllerType);? Or, should I use a different approach altogether?

like image 878
quakkels Avatar asked Sep 26 '11 19:09

quakkels


People also ask

How do I add a class to my controller?

Creating a Controller Class Follow these steps: Right-click the Controllers folder and select the menu option Add, New Item and select the Class template (see Figure 4). Name the new class PersonController. cs and click the Add button.

How does MVC know which controller to use?

Also, MVC relies heavily on reflection, which allows you to inspect types at runtime using strings. Reflection is used in many programming frameworks.


1 Answers

Reference the other assembly from the 'root' ASP.NET MVC project. If the controllers are in another namespace, you'll need to modify the routes in global.asax, like this:

public static void RegisterRoutes(RouteCollection routes) {     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");      routes.MapRoute(         name: "Default",         url: "{controller}/{action}/{id}",         defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },         namespaces: new[] { typeof(HomeController).Namespace }     );  } 

Notice the additional namespaces argument to the MapRoute method.

like image 109
Mark Seemann Avatar answered Oct 08 '22 09:10

Mark Seemann