Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plug-in architecture for ASP.NET MVC

Tags:

asp.net-mvc

I've been spending some time looking at Phil Haack's article on Grouping Controllers very interesting stuff.

At the moment I'm trying to figure out if it would be possible to use the same ideas to create a plug-in/modular architecture for a project I'm working on.

So my question is: Is it possible to have the Areas in Phil's article split across multiple projects?

I can see that the name spaces will work themselves out, but I'm concerned about the views ending up in the right place. Is it something that can be sorted out with build rules?

Assuming that the above is possible with multiple projects in a single solution, does anyone have any ideas about the best way to make it possible with a separate solution and coding to a predefined set of interfaces? Moving from an Area to a plug-in.

I have some experiences with plug-in architecture but not masses so any guidance in this area would be useful.

like image 850
Simon Farrow Avatar asked Dec 04 '08 10:12

Simon Farrow


People also ask

What is plugin in ASP.NET MVC?

The ASP.NET MVC plugins is actually a extension based on another plugin framework OSGi.NET, technically, you can replace it with any other frameworks like MEF, Sharp-develop with some wrapping.

What is ASP.NET MVC architecture?

The ASP.NET MVC framework is a lightweight, highly testable presentation framework that (as with Web Forms-based applications) is integrated with existing ASP.NET features, such as master pages and membership-based authentication. The MVC framework is defined in the System.

What are the three different architectural components of ASP.NET MVC?

Let's understand the MVC architecture supported in ASP.NET. MVC stands for Model, View, and Controller. MVC separates an application into three components - Model, View, and Controller.

What is .NET plugin?

The plugin framework is a NuGet package that allows you to customise and extend a . NET application at runtime. Code examples are provided for ASP.NET Core, Blazor, Console Apps and WPF & WinForms. The plugin framework package can be installed from NuGet and also supports the delivery of plugins from NuGet.


2 Answers

I did a proof of concept a few weeks ago where I put a complete stack of components: a model class, a controller class and their associated views into a DLL, added/tweaked one of the examples of the VirtualPathProvider classes that retrieve the views so they'd address those in the DLL appropriately.

In the end, I just dropped the DLL into an appropriately configured MVC app and it worked just like if it had been part of the MVC app from the start. I pushed it a bit further and it worked with 5 of these little mini-MVC plugins just fine. Obviously, you have to watch your references and config dependencies when shuffling it all around, but it did work.

The exercise was aimed at plugin functionality for an MVC-based platform I'm building for a client. There are a core set of controllers and views that are augmented by more optional ones in each instance of the site. We're going to be making those optional bits into these modular DLL plugins. So far so good.

I wrote up an overview of my prototype and a sample solution for ASP.NET MVC plugins on my site.

EDIT: 4 years on, I've been doing quite a few ASP.NET MVC apps with plugins and no longer use the method I describe above. At this point, I run all of my plugins through MEF and don't put controllers into plugins at all. Rather, I make generic controllers that use the routing information to select MEF plugins and hand the work off to the plugin, etc. Just thought I'd add since this answer gets hit a fair bit.

like image 89
J Wynia Avatar answered Sep 22 '22 16:09

J Wynia


I’m actually working on an extensibility framework to use on top of ASP.NET MVC. My extensibility framework is based on the famous Ioc container: Structuremap .

The use case I’m trying to fulfill is simple: create an application that should have some basic functionality that can be extended for every customer (=multi-tenancy). There should only be one instance of the application hosted but this instance can be adapted for every customer without making any changes to the core website.

I was inspired by the article on multi tenacy written by Ayende Rahien: http://ayende.com/Blog/archive/2008/08/16/Multi-Tenancy--Approaches-and-Applicability.aspx Another source of inspiration was the book of Eric Evans on Domain Driven Design. My Extensibility framework is based on the repository pattern and the concept of root aggregates. To be able to use the framework the hosting application should be build around repositories and domain objects. The controllers, repositories or domain objects are bind at runtime by the ExtensionFactory.

A plug-in is simply an asselmbly that contains Controllers or Repositories or Domain Objects that respects a specific naming convention. The naming convention is simple, every class should be prefixed by the customerID e.g.: AdventureworksHomeController.

To extend an application you copy a plug-in assembly in the extension folder of the application. When a user request a page under the customer root folder e.g: http://multitenant-site.com/[customerID]/[controller]/[action] the framework check if there is a plug-in for that particular customer and instantiate the custom plug-in classes otherwise it loads the default once. The custom classes can be Controllers – Repositories or Domain Objects. This approach enables to extend an application at all levels, from the database to the UI, through the domain model, repositories.

When you want to extend some existing features you create a plug-in an assembly that contains subclasses of the core application. When you’ve to create totally new functionalities you add new controllers inside the plug-in. These controllers will be loaded by the MVC framework when the corresponding url is requested. If you want to extend the UI you can create a new view inside the extension folder and reference the view by a new or subclassed controller .To modify existing behavior you can create new repositories or domain objects or sub classing exiting ones. The framework responsibility is to determine which controller/ repository / domain object should be loaded for a specific customer.
I advise to have a look at structuremap (http://structuremap.sourceforge.net/Default.htm) and especially at the Registry DSL features http://structuremap.sourceforge.net/RegistryDSL.htm .

This is the code I use at the startup of the application to register all plug-in controllers/repositories or domain objects:

protected void ScanControllersAndRepositoriesFromPath(string path)         {             this.Scan(o =>             {                 o.AssembliesFromPath(path);                 o.AddAllTypesOf<SaasController>().NameBy(type => type.Name.Replace("Controller", ""));                 o.AddAllTypesOf<IRepository>().NameBy(type => type.Name.Replace("Repository", ""));                 o.AddAllTypesOf<IDomainFactory>().NameBy(type => type.Name.Replace("DomainFactory", ""));             });         } 

I also use an ExtensionFactory inheriting from the System.Web.MVC. DefaultControllerFactory. This factory is responsible to load the extension objects (controllers/registries or domain objects). You can plugin your own factories by registering them at startup in the Global.asax file:

protected void Application_Start()         {             ControllerBuilder.Current.SetControllerFactory(                 new ExtensionControllerFactory()                 );         } 

This framework as a fully operational sample site can be found on: http://code.google.com/p/multimvc/

like image 42
Geo Avatar answered Sep 22 '22 16:09

Geo