ASP.Net MVC Portable Areas via MvcContrib

Follow me on RSS and Twitter

 

This is a multi post series on ASP.Net MVC Portable Areas

What is a Portable Area?

A Portable Area is a set of reusable multi page functionality can be dropped into an application to provide rich functionality without having to custom build functionality that is literally the same in every application. This could be considered a plug-in or add-in type of functionality.  The portable portion of this approach is that the area can be distributed as a single assembly rather than an assembly and a host of other files, like views or other html assets that need to be managed and maintained over time.  By making a portable area totally self contained in a single assembly, this should allow for easier reuse and upgrades to the area.  The challenge for doing something like this has been how do you allow enough control over the User Interface by the application yet still allow the actual views to be packaged with the logic.

Why Now?

There has been some discussion in the past on the MvcContrib mailing list about creating an plug-in framework and plugins but I do not think we had enough of the pieces in place to do this properly.   I believe that with MVC 2 we have those missing pieces figured out.  The first enabler is the inclusion of Areas into the MVC 2 feature set. This includes having the Area and Controller namespace become part of the route data which is used both for Controller/Action selection but this also flows down to the selection of a view. The second enabler is some of the work that came out of MvcContrib and the Input Builders.  While implementing that feature we came up with a way to pull views from an assembly as an embedded resource.  This with the ability to override the default view engine in a way that allows an application developer to place their own version of a view in a folder so that they have the option to change the view to their needs was huge.  The last enabler really comes from what we have learned from all of the SOA greats and see how frameworks like nServiceBus and MassTransit have demonstrated that a messaging approach for integration can keep our concerns separated.

The other why now is that my company, Headspring, has found that in order to make our practice more successful, we need the ability to drop in some of the essentials for an application, we would prefer to do this in a binary form that is easy to upgrade and does not leave us with copy and pasted code between our various projects.  We would like to see that if we learn something from one project that we have the potential to apply those learning’s to projects that are still in flight. We all prefer that rather than waiting for the next project to start so that we can apply what we have learned to the new project.  This approach will be much better for us as developers and our client will benefit as well.  We could take the approach of working on this in a bubble but by putting this out for the community we can learn from every else and potentially help others in the process and raise the collective bar for the industry, in our own little way.

 

Logical View of a Portable Area

Below is a logic view of a Portable Area.  It shows how the Green block is an application.  Inside the application the blocks in dark blue are framework components in ASP.Net MVC 2 and MvcContrib.  These blocks provide some minimal framework support for registration view resolution and communication between the application and the portable area.  The light blue blocks represent code the developer create.  The code in the Portable Area is created by the Portable Area developer. The code in the application block is coded by… you guessed it. The application developer.

image

Thanks for the Pictures but where is the code?

The code is currently available in the MvcContrib MVC 2 Branch.  You can get the latest binary from our (TeamCity/CodeBetter) build server here:  http://teamcity.codebetter.com/guestAuth/repository/download/bt83/.lastSuccessful/MVCContrib.release.zip

There is a sample application you can download here: http://teamcity.codebetter.com/guestAuth/repository/download/bt83/.lastSuccessful/MVCContrib.Extras.release.zip

or from the code repository on GitHub:  Download the source as a zip.  or Fork it on GitHub.

Follow me on RSS and Twitter

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Eric Hexter

I am the CTO for QuarterSpot. I (co)Founded MvcContrib, Should, Solution Factory, and Pstrami open source projects. I have co-authored MVC 2 in Action, MVC3 in Action, and MVC 4 in Action. I co-founded online events like mvcConf, aspConf, and Community for MVC. I am also a Microsoft MVP in ASP.Net.
This entry was posted in .Net, Asp.Net MVC, mvc, mvccontrib, Open Source Software, OSS. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.codebetter.com/blogs/glenn.block Glenn Block

    Nice Eric. Looking forward to seeing how the posts play out.

  • Martin

    I think you should make it clear that your bus is internal (for application process) and synchrounus when you compare to NServiceBus for example.
    What I mean is this:

    LoginController.Index
    var message = new LoginInputMessage {Input = loginInput, Result = new LoginResult()};
    PortableArea.Bus.Send(message);
    if (message.Result.Success)
    {

    }

    Bus.Send would be a asynchrouns call in NServiceBus. Note, I haven’t used NServiceBus but I think it works like that.

    Anyhow, I will follow this with great interest.

  • http://www.adverseconditionals.com Harry M

    Is there any way to get something like this to work with MVC 1?

  • http://www.lostechies.com/members/erichexter/default.aspx erichexter

    @Martin, Great point, by no means is this meant to do what the actual Bus projects do. I will update the post to make that more clear.

    @Harry, right now this will not work with MVC1 as it is built on top of the area implementation, but once this shakes out if there is really some barrier to upgrading from MVC 1 to MVC 2, we could look into back porting the area support into MvcContrib. Although upgrading to MVC 2 will actually be pretty simple so, once this gets baked we could talk about why you would want to stay on mvc 1 and than what we could do to make it work on that version of the framework.

  • http://haacked.com/ Haacked

    Does this work in Medium trust on ASP.NET 3.5 SP1?

  • http://www.lostechies.com/members/erichexter/default.aspx erichexter

    @Haacked , this approach does not work with Medium Trust. we need to get the ASP.Net team to fix that!

  • http://haacked.com/ Haacked

    @erichexter it has been fixed on ASP.NET 4. Try it out!

  • TJ

    Very cool Eric, i like the use of a message bus. Correct me if I’m wrong but since the portable areas are required to be referenced by the host application and then compiled, you don’t get assembly drop-in functionality with this approach.

    This combined with MEF for true pluggable areas is the next step perhaps? :)

  • http://www.lostechies.com/members/erichexter/default.aspx erichexter

    @TJ, this is correct you do not get a drop in area. But part of that reason is the way that the default area registration occurs. In Preview 2 the area registration only scans assemblies that are referenced from the main UI application. If this is change than the they could be drop in a bin as long as that portable area does not require some sort of communication with the host application. If it can carry along all of its data, configuration, and logic than it could be dropped in.

  • http://www.adverseconditionals.com Harry M

    We’re starting a new feature soon, and I’ve been pushing feature-based application partitioning. I don’t think the powers that be will allow us to go live on a beta or CTP unfortunately, so it would be great to get this into MVC1.

    There’s a couple of other things I’d love to see with this, which I’m not sure this solution handles, but I would be cool if it did.

    Firstly, when the parent app registers the areas, it would be nice if it could modify the routes, maybe applying a prefix to them. i.e. this means two independent areas could both use the /settings url, but the host app could choose to make the routes something like area1name/settings and area2name/settings.

    The other thing is related to master pages/visual inheritance/subcontroller routing. It would be extremely neat if a master application could intercept routes registered in child areas, run them through a master controller and action in the parent, which would output containing html with a ContentPanel (like a master page), maybe register a couple of request scoped services, and then call the child area with a slightly rewritten request to produce the html to go inside the ContentPanel.

    Hmm. I may need to explain myself better.

  • Caladin

    I have to say this solves my biggest complaint about MVC.
    Too much copy and paste of common code and all the headaches that it generates.

    Thanks!

  • http://www.lostechies.com/members/erichexter/default.aspx erichexter

    @HarryM I am not sure I follow you on the Hosting Application owning the routes. I was thining that if a single area was a multi-tenant than it could add its instance to its routes.. like /{Area}/{Instance}/{Controller}/{Action}

    Right now if the Portable Apps use the same master page name this will all work out but realistically that becomes a little difficult to manage, so I was thinking that there should be a way for the application to tell the Portable Area what it should use as its master page, then the PA would be responsible for specifiing that whenever it creates a ViewResult from an action.

    @Caladin, glad to hear.. I think it has a lot of potential.

  • Randy H

    Is there a problem with the latest version of ASP.Net MVC 2 Beta (released 11/17/2009)? When running your MvcContrib.Samples.PortableAreas sample I am getting this error:
    The view ‘index’ or its master was not found. The following locations were searched:
    ~/Areas/Login/Views/login/index.aspx
    ~/Areas/Login/Views/login/index.ascx
    ~/Areas/Login/Views/Shared/index.aspx
    ~/Areas/Login/Views/Shared/index.ascx
    ~/Views/login/index.aspx
    ~/Views/Shared/index.aspx
    ~/Views/InputBuilders/index.aspx
    ~/Views/login/index.ascx
    ~/Views/Shared/index.ascx

  • Nilesh Hirapra

    Look here for solution. Putting detailed steps very soon.
    http://nileshhirapra.blogspot.in/2012/02/aspnet-mvc-pluggable-application.html

  • http://www.thoughtresults.com Saeed Neamati

    I think you do need to explain a little more about the way of achieving this “Portable Area” thing. I downloaded the code, but reverse-engineering a code is really harder than somebody explaining it to you. Your article is valuable in concept and idea, but lacks the necessary description. Thanks.