Some of the most difficult aspects of consuming PortableAreas (PAs) are MasterPages and ContentPlaceHolders.  The embedded views of a PA are hard coded to use Site.Master, which may be inconsistent with the host application.  It works, but it can be much better.  After some discussion on twitter with Eric Hexter and Steve Michelotti, I had an idea for solving the problem.  I’ll soon submit a pull request.

Host Application – Wiring Things Up

In your application, you surely have your own MasterPage.  That MasterPage has ContentPlaceHolders, probably with IDs that conform to the coding standards of your particular project.  The goal is to use a PA, and make it feel like a seamless part of your application.  To do that, you need some way to tie everything together.

Hypothetically, you wish to utilize “SomePortableArea” with your application.  Inside of your Global.asax.cs, during Application_Start() you can map the PA to your MasterPage and its ContentPlaceHolders like this:

Content.Map<SomePortableAreaMap>()

    .Master("~/Views/Shared/MyApplication.master")

    .Title("PageTitle")

    .Body("BodyContent");

 

AreaRegistration.RegisterAllAreas();


The Content static class has a Map<>() method that returns an instance for the given map type.  The type you provide depends on the PA you’re working with.  The imaginary SomePortableArea.dll has a class called SomePortableAreaMap.  Thus, the example calls Map<SomePortableAreaMap>() to get the map.

PortableAreaMap has three extension methods:

Master() - Tells the PortableArea what MasterPage to use.
Title() - Tells the PortableArea what the Title ContentPlaceHolderID is in the MasterPage.
Body() - Tells the PortableArea what the Body ContentPlaceHolderID is in the MasterPage.


*In order for the mappings to work, they must be done before the areas are registered.

Here is a look at the markup in “MyApplication.Master”:

image

Creating PortableAreas – Providing a Map Class

As the author of a PortableArea, now you can feel confident that people won’t send nasty grams about how your PA ruined their conventions!  Even more good news: it’s not that difficult for you to implement.  Imagine that you’re the author of “SomePortableArea.”  You would define a class like this:

public class SomePortableAreaMap : PortableAreaMap

{

    public SomePortableAreaMap()

    {

        DefaultMasterPageLocation = "~/Views/Shared/Site.Master";

        DefaultBodyID = "MainContent";

        DefaultTitleID = "TitleContent";

    }

}


Inherit from PortableAreaMap, and provide some default values in the constructor.  These default values come from the MasterPage that you have in your project (mostly for intellisense & View generation reasons):

image

There is just one part left, and that is to override a new method in SomePortableAreaRegistration:

public class SomePortableAreaRegistration : PortableAreaRegistration

{

    // ... other code

 

    public override PortableAreaMap GetMap()

    {

        return Content.Map<SomePortableAreaMap>();

    }

 

    // ... other code

}


This just grabs the Map for your portable area, using the SomePortableArea type defined earlier.

Extensibility

One way that you might be able to extend the portable area is to use another <asp:Content> tag in your views, perhaps ContentPlaceHolderID="JavaScriptContent" to make sure all of your area’s JavaScript gets rendered to the bottom of the page.  You could then add a method to SomePortableAreaMap, allowing the host to map it to one of their ContentPlaceHolders:

public SomePortableAreaMap JavaScript(string name)

{

    Add("JavaScriptContent", name);

    return this;

}


Summary

Host applications are able to configure a PA to use their MasterPages by calling chainable methods.

PortableAreas provide a PortableAreaMap, making the former possible.  By providing a map class, the PA can more easily support another ContentPlaceHolder (i.e. for JavaScript).  Then, the consuming application can create a special MasterPage, or nest MasterPages to accommodate the PA, all the while retaining their freedom of conventions.

Hopefully this is easy to understand.  The steps seem fairly intuitive, and simple to me (but then again, I’m biased… after all, I wrote it!).  What do you think?

Friday, May 21, 2010 12:27:58 AM (Eastern Daylight Time, UTC-04:00)  #    Comments [0] -
MvcContrib | Portable Areas
Comments are closed.

John Nelson

mugshot I am a passionate C# Developer working in ASP.NET on an e-commerce solution for ticketing software. I work across all of the application layers, including server side functionality, and client side programming with jQuery and MS Ajax. Although my full time job is in WebForms, I spend many of my off hours working with MVC. I am especially interested in productivity and good programming practices.

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2010
johncoder.com
Statistics
Total Posts: 41
This Year: 17
This Month: 0
This Week: 0
Comments: 4