I recently came across a way to develop pluggable application modules when using ASP.NET MVC3/4 and I loved the simplicity of the approach. Currently, I have my applications
Don't create the Areas in the hosting web app, but create separate projects, that compile to separate dll's. Copy the dll's to any web app where you want to use it. Remember to set all static files as "EmbeddedResource".
You can use MvcContrib PortableAreaRegistration's "Bus" to send messages, commands from the portable area to anyone on the 'bus'. That can be the hosting web app, or in theory independent Area's can send message to each other.
Created two crude, but functional demo of this, code on github:
https://github.com/AkosLukacs/PluggablePortableAreas
https://github.com/AkosLukacs/PluggablePortableAreasMVC4
First, you define a message that can carry the information you need. Just a POCO that has some properties (PluggablePortableAreas.Common\RegisterAreaMessage.cs):
public class RegisterAreaMessage : IEventMessage
{
public string LinkText { get; private set; }
public string AreaName { get; private set; }
public string ControllerName { get; private set; }
public string ActionName { get; private set; }
//...
}
Create a handler for that message type (PluggablePortableAreas.Common\RegisterAreaEventHandler.cs):
public class RegisterAreaEventHandler : MessageHandler{}
In this case, the MessageHandler just adds the received messages to a static ConcurrentBag
. You can use DI, if you want to, but wanted to keep it simple.
You can send the message from the portable area like this (Areas\DemoArea1\Areas\Demo1\Demo1AreaRegistration.cs):
//the portable area sends a message to the 'bus'
bus.Send(new RegisterAreaMessage("Link to the Demo area", AreaName, DefaultController, DefaultAction));
The dynamically added links are displayed by iterating over the collection of messages(PluggablePortableAreas.Web\Views\Shared_Layout.cshtml):
@foreach(var sor in PluggablePortableAreas.Common.RegisterAreaEventHandler.RegisteredAreas) {
- @Html.ActionLink(sor.LinkText, sor.ActionName, sor.ControllerName, new{Area=sor.AreaName}, null)
}
One more thing to take care of: Use "fully qualified" Area names. If you don't specify the area name explicitly, MVC assumes it's the current area. No problems without areas, but the second will point to "/path_to_your_app/CurrentArea/Home"
instead of "/path_to_your_app/Home"
.
- @Html.ActionLink("Home", "Index", "Home", new { Area = "" }, null)
- @Html.ActionLink("I don't work from the portable area!", "Index", "Home")
The development server in VS feels a bit "erratic", sometimes the portable area doesn't load. Works reliably in full IIS tho...