Building a Composite MVC3 Application with Ninject

So there’s great support in Prism to building composite applications with Silverlight with the notion of Prism modules. They have a nice discovery approach for dynamically discovering modules when loading XAPs and assemblies during runtime for all the different modules your Silverlight app may need. You can load them during start-up or on demand so that you don’t have to download the entire application at one time.

When building an enterprise MVC application, I wanted to borrow some of the ideas and architecture of the Prism extensible plug and play concepts to provide the ability to build modules (areas) of your MVC application outside of your core MVC application.

For example if you had a MVC application and it’s primary role is an E-Commerce site (core site), however you have this new requirement to build a integration point to show customers all their tracking statuses for their orders. Now you have to ramp up a development team as quick as possible so that they can build out this feature, however you now find yourself giving them a full blown training and overview of your core MVC application, full source control of your entire VS Solution set which could have up to 20-30 projects in it.

Now when devs from the team compile it’s taking forever…! Here we can easily see that our MVC app’s footprint is getting to large and somewhat difficult to manage. So here is now the need to break it down into blocks that can be injected into the app during runtime so that development for these different pieces, blocks, or modules can happen in parallel with your core MVC application (loose coupling, modularity and extensibility).

My preference here is to actually use Mef since I have experience with it and the great support for MVC3 and Mef now. However, I’ve been given the opportunity to be engaged on a project that uses Ninject. With this being the situation at hand I wanted to explore and see if we could borrow the some concepts from Prism, and incorporate them using what was out of the box with Ninject. Some of these concepts include separation of concerns and loosely coupled components (modules) that can evolve independently but can be easily and seamlessly integrated into the overall application, which is also known as a composite application.

So after a little bit of poking around with Ninject, I quickly found that Ninject also has a notion of Modules, NinjectModules, or classes that implement the INinjectModule interface. You can ask the Ninject Kenerl (container) to scan an assembly and it will scan for all any classes that implement INinjectModule, this can be done directly by implementing the actual interface or inheriting their out of the box NinjectModule abstract class.

This is a C# class library where all the plugin infrastructure classes will reside

MvcApplicationA.Plugin

Example PluginA

MvcApplicationA.Plugin

Example PluginB

MvcApplicationA.Plugin

Example PluginB

Let’s take a quick look at some of the classes in the MvcApplication.PluginFramework VS Project.

MyController.cs (implements IMyController)

All controllers from plugins will need to inherit MyController, this provides some meta-data so that we can infer the correct type of a plugin Controller from our IoC that was requested.

MyPlugin.cs

There will be one class in each plugin that must inherit MyPlugin, this class provides meta-data about the plugin, e.g. PluginName, AssemblyName, etc.. It also gives us the overidable Load operation where we can setup our Ninject bindings e.g. Controller and plugin bindings.

MyControllerFactory.cs

We inherit the DefaultControllerFactory and override the GetControllerType method so that when a user is routed to a controller that is in a plugin, we can help the MVC runtime derive what it’s type is by scanning our IoC for registered instances for that a given Controller and return it’s type.

As requirements changed and the project matures, it will be helpful that we can change parts of the application without having these changes cascade throughout the system. Modularizing an application allow you to build application components separately (and loosely coupled) and to change whole parts of your application without affecting the rest of your code base.

Hi. it’s a good post but i have a question how i can inject or add a plugin without restart the web server, i tried coping the dll and files but when try access to resource the page is not found, if i restart the server then the page is displayed. Thanks in advance. :)

I have the same issue,i tried to replace the existing plugin dll with the modified one but i can’t and gives me the message that the folder is in use. Is there any other way than to restart app pool.Thanks in advance.

I think it depends. With this IoC approach you have more control over the plugins and the structure of your application. You can use many features of the IoC’s like policy injection and interception. Unlike Long Le, I don’t see the dependancy on an IoC as a negative thing. In real world application you need an IoC for many reasons. So why not use that for composition of the Area’s, too?

I think that this approach give much more control over your application and the added plugins. But it’s just me :-)

It would be even better if there was a way to add plugins without restart the application.

This rocks, great tutorial man, exactly what I need. Is there any license involved in using this code? I want to use it in what will be a commercial app, and don’t want to tread on anyones toes so to speak.

Oh of course, I’ll credit you and the blog post no problems.. in all classes referenced.. it’s just awesome that dedicated coders like you are providing such good solutions for free.. I’d honestly never thought of using Ninject like this, but it’s an amazingly elegant approach, and seems to minimize any Reflection needed.. many thanks, and have a great New Year :D

Hi, can i also ask a question. How can i use partials from plugins in main MVC solution. For ex. in About view how can i use @Html.Action(“PlaginA”,”Index”)? when I try to do this it returns an error Server Error in ‘/’ Application.
The controller for path ‘/Home/About’ was not found or does not implement IController.

hi,
this is really great article, but i have one question, how could we install plugins by user?
what i mean is after the project is compiled, and uploaded online, later i develop a plugin and copy it to the plugins directory, how can i install it or make the application aware of it without recycling or recompiling the app?

You could create a view for a user/developer to upload there project (.zip) programmatically decompress it and copy it to the right folder. Post the copy, you could use the Ninject Kernel to scan the assemblies so that all the Controllers for the plugin are registered with Ninject’s IoC container, in theory this should not require a recycle.

Thanks a lot man for reply, and i read your other article which is brilliant too, but i think MVC main application wont see the routes, modelbinders, etc. because i have tried to do what you suggested and used ninject Kernal and it loaded fine but not routes, Modelbinders, etc….