Wednesday, February 29, 2012

ASP.NET MVC - Pluggable application modules/components/area/features

This article discuss about how to develop ASP.NET MVC application which has loosely coupled modules (or features) which can be developed separately without any directly dependency and those modules can be plugged-in to main application without any extra bit of code.

Business Value:
This is specifically useful for product development. Using this approach, each module can be developed separately and deployed/shipped with product separately. This helps in building different version of product like: Basic, professional, premium and enterprise. This loosely coupled feature approach enables to either build separate installer with required features as per different versions or master setup which can install only defined features as per license key used during installation.




Building application:
Below step by step process demonstrates how to build application with pluggable modules/areas in ASP.NET MVC 3.
Suppose we want to build a product which has following modules:
1.      Marketing
2.      Sales
3.      Billing
4.      Inventory
5.      Warehouse
And we want to build a product which allows selling/distribution/deployment of each above modules as separate feature. Typically such products will have some basic features/infrastructure and these modules will fit on top of that. So let’s assume we have basic application with master page, landing page, authentication, security, logging and related resources. We will build application with pluggable modules/component/features for above modules.

Open visual studio and create empty ASP.NET MVC 3 project. Select empty template from below step. (I have named Project/solution as ProductDemo in this example).

You will see empty project in solution explorer like blow:
Now click on Controller to add HomeController, select Empty controller for Template.

Create index view for HomeController to provide landing page of application.

Pluggable modules menu items and expected output:
_Layout.cshtml (Views\Shared folder) is configured to create menus pointing to each above expected modules.

With this, output of application now looks like below:








Creating Areas folder structure and get sample of XXXXAreaRegistration file:
Now click on Project and select Add->Area from context menu. This step will create basic folder structure for Area framework. Specify Marketing as Area name and complete step. This will now create Areas folder and folder structure for Marketing with XXXXAreaRegistration.cs file.
Now take a backup of MarketingAreaRegistration.cs file since we are going to delete Marketing folder in next step. This file will be useful when we will add Marketing module in solution as separate project. (This file can also be created manually once structure is understood).
Now remove Marketing folder.
Adding Pluggable module/area to ASP.NET MVC Project:
Now we are about to start project of added new pluggable module for ‘Marketing’. Right click on solution and choose option to add new project. In below dialog box do following:
·        Select ASP.NET MVC 3 Application
·        Name project as ‘Marketing’
·        Set Location as …\ProductDemo\Area
New project should be created in Areas folder we created in just few seconds before. Create project with empty template.
From newly created “Marketing” project, remove Content folder, scripts folder, view/shared folder and global.ascx file. These are added as part of full MVC project but not needed for us since we are creating this as pluggable module/area.  After this step, solution should look like following:
Since we saved new project marketing under Area folder, it is appearing as hidden folder in ProductDemo/Area folder in solution explorer. DO NOT include this folder in project.
Add MarketingAreaRegistration.cs file at project root in marketing project and change its namespace to match with project name spaces, like below:














Now set output directory of Marketing project to ..\..\bin\ so that compiled dlls are placed in bin directory of ProductDemo (Main application) application.
In marketing project, modify web.config file to remove connection strings, authentication, membership, rolemanager, profile etc sections.

Now create controller Marketing (You can have any other controller as well) in Marketing project. Create index view and place content “Welcome to Marketing Module” like below:


Now application is ready with marketing module. Compile the solution to build all projects in solution. After compilation take a look at ProductDemo\bin folder and you will see compiled dlls like below:


Now run application to see its working. Click Home and Marketing links to see how application is switching between main application shell and marketing module.


Repeat all steps of “Adding Pluggable module/area to ASP.NET MVC Project” section to define rest all modules.


How this works?

ASP.NET MVC Areas structure enables creating separate logical modules and those still resides in same project and binary. Notice xxxAreaRegistration.cs in marketing (or any new project added as per this process) which is inherited from AreaRegistration. This file tells two things to ASP.NET MVC and Routing framework: 1) Area name and Rout for accessing Area and its controller actions.

Global.ascx.cs in Main application (ProductDemo) has following code block. This block registers all areas defined in all assembly present in application bin directory. Remember we have directed output of marketing module to main application bin directory.

Application Master Page - main application has master page (_Layout.cshtml) which is at parent directory in ASP.NET application. As per ASP.NET framework, this layout is inherited to its all sub directories. This way even if marketing is separate project it inherits master page of main application and same applies to all other resources like CSS, image, javascripts and other static resources/pages.


What more can be done?
·        Menus to access such modules can be built dynamically by looking at directories/module directory under Areas folder. If area present in folder, construct menu for its pages and show it on application.
·        Consume WCF service in application. WCF services which are common among main application and module/area project, those needs to be referenced in both the project. Any service which is only required for module, should only be referenced in module.
·        CSS and images can be divvied in such a way that all common resources reside in main application content folder and referenced in _Layout.cshtml. CSS, image and other resources which are specific to module can be placed in module. One more layout page can be introduced at module level which is inherited from main application layout page.
·        Create installer (setup) to package such pluggable modules and install them on web server under IIS. Refer Installer - ASP.NET MVC - Pluggable application modules/components/area/features

Source Code: Download Project

25 comments:

MartinH said...

Best Job ! Nice post. I want to build modular aplication with MVC 3 RAZOR engine and this is good start. But I have Question. It is possible to make installation module easier, for users ? Can I make module Active or Disable ? Is it Complicated ? Can you help me with some idea how to integrate this module system to web site administration ? Thank you !

Nilesh Hirapra said...

Martin,
Refer TechTalk: Installer - ASP.NET MVC - Pluggable application modules/components/area/features. Hopefully this would be helpful.

MartinH said...

WOW, thanks for your prompt reply ! I appreciate your answer and I hope that you will continue with this topic. For example little administration for modules. Sorry for me english :)

Anonymous said...

nice post!, much appreciated if you add code too

Nilesh Hirapra said...

Download link added.

REiKen said...

Thanks!
It is simple and great!

Frantisek said...

Nice post.

Just would like to know, why IIS is starting for every module. When I add second module, 3 IIS are starting...

Thank you

MartinH said...

Hello, I Have problem with link in area. When I create action link within area this way: @Html.ActionLink("Home", "Index", "Home", new { Area = "" }, null) visual studio tell me that Action index and contoller Home does not exist´s. The same with other link (images, css) whitch are placed on the root of project. Thanks for help !

Unknown said...

Nice post, its similar to the portable areas. Just simple question How do you use layout? I would like to have layout in order to have same design without copy layout page... any ideas?

cjjubb said...
This comment has been removed by the author.
Haritha said...

Very useful post. Thank you very much. Keep it.

Jokie said...

Thanks for the Post. I have a question.

I am using MVC4 and everything works except for the things todo - "One more layout page can be introduced at module level which is inherited from main application layout page."

So I tried to create a module layout as described here "http://www.mikesdotnetting.com/Article/164/Nested-Layout-Pages-with-Razor"

Problem is I cannot get the "Layout = "... /_ModuleLayout.cshtml";"
to find the module layout.
How would one reference the module layout to work as a nested layout?

Thanks.

ngocthai said...

Thank you very much, Nilesh Hirapra.

Hiral said...

Thanks Nilesh for such an amazing post.
I am new to the ASP.Net and I want to create same types of application which some changes. The link for my requirement is http://stackoverflow.com/questions/13649686/how-to-create-a-pluggable-installable-module-based-application-in-asp-net

I would appreciate your feedback.

Hiral said...

Thanks Nilesh for such a informative post.

I need same kind of application with some changes.

I described my requirements on the link: http://stackoverflow.com/questions/13649686/how-to-create-a-pluggable-installable-module-based-application-in-asp-net

I would appreciate if you would comment on it.

Thanks

Hiral said...

Thanks Nilesh for such a informative post.

I need same kind of application with some changes.

I described my requirements on the link: http://stackoverflow.com/questions/13649686/how-to-create-a-pluggable-installable-module-based-application-in-asp-net

I would appreciate if you would comment on it.

Thanks

Suman Rocks said...

Can you give some explanation on publishing this website. Do we have to publish each side individually? Since when I am publishing the main site "ProductDemo" it's not including "Marketing" in it

Cory Koski said...

Hey Nilesh, I took the liberty of updating your article to make it work with ASP.NET MVC 4. You can check it out here: http://geekswithblogs.net/cokobware/archive/2013/01/15/asp.net-mvc-4-pluggable-application-modules.aspx

I've credited you with original authorship for this great article and technique.

Hari said...

Can we use this areas for web portal kind of aplications.Like my main application will be checking all the corresponding authentication.and based on the authorization I will adding the more areas.Do I need to build the soluition all the time...I am confused.Can you please explain how it works when you add new application/area.

Andrew Stoute said...

Great job, this was exactly what I was looking for.

However, I have a question:

When you run this in Visual Studio to debug a webserver gets spun up for each project you have in the "Areas" section. For example: I've utilized your approach and have 1 main project with 3 other sub-peojects in the Areas section. When I hit F5 to debug 4 web servers spin up, 3 of which are not needed. Do you know of a way to stop this, so only the one web server that's needed starts?

Ivo said...

I wanted to know if i could override the views/COntrollers for different clients.

Unknown said...

nice post.. but am create a three projects in same solution so how can access one projects values to another please help me it's urgent for me..

Unknown said...

Thanks Nilesh,
The code attached does not show the Marketing page by default.

It will be very nice if you can specify the default controller in MarketingAreaRegistration class.

Anonymous said...

Best Job!thanks alot.
I need help. I have try this but always get the same Error that the Ressource in Areas habe being remove. can someone please help me!!
thanks

Anonymous said...

Just a question. Why do we need to point the directory of the modules project into the core Areas directory? Is that required?