As far as I can tell, Monorail is planning to support nested layouts (master pages) but doesn't currently do so.
In my current Monorail project I need to be able to support 1,2, and 3 column layouts in my #content section of my pages. I use css for layout and accessibility support so my markup remains the same in my layout with columns added or disappearing based on the css I hand it.
Since I can't use the 'CaptureFor' component within my layout pages, I needed to come up with some alternative way of passing the css that overrides my base layout css and keeps me from having to maintain multiple layout pages that are only differing by the <head/> content.
So first my <head/> inside 'default.brail':
<head>
<title>Company Name</title>
<link href="${siteRoot}/Content/css/base.css" rel="stylesheet" type="text/css" />
<!--implementor pages can inject styles here-->
${?styles}
${Ajax.InstallScripts()}
${Scriptaculous.InstallScripts()}
${ValidationHelper.InstallScripts()}
<script type="text/javascript">
<!--implementor pages can inject javascript here-->
${?javascripts}
</script>
</head>
Note the ${styles} parameter that I can use either from my views using the CaptureFor component, or as we'll see, in a Filter.
Now suppose I want to attach the LayoutAttribute to an action/controller. I can do Layout("default2column") and then let a Filter parse that attribute to handle the css injection:
if(controller.LayoutName!=null)//ajax calls won't have a LayoutName
{
if (controller.LayoutName.ToUpper() == Settings.Default.LAYOUT_TWO_COLUMN.ToUpper())
{
controller.PropertyBag["styles"] =
string.Format(Settings.Default.CSS_LINK, Settings.Default.LAYOUT_TWO_COLUMN);
} controller.LayoutName = "default"; //don't pass layout name or else your ajax response will have it included...bad
}
return base.OnBeforeAction(context, controller);
First, I determine what layout name was assigned to the action ("default2Column"), then I can inject my desired css into the 'styles' view parameter. Finally, I switch the layout name to 'default' so that Monorail won't go looking for a layout called 'default2Column'. This allows me to have ONE default layout and use css to handle my layout...exactly what I want to do and beats managing multiple layouts.
BTW, I am using the 'Holy Grail' layout for 3 column, fluid content with minor modifications to deal with IE7 funniness.
If anyone is interested, I'll post the markup and css to show how to toggle between 3 and 2 column layouts with about 4 lines of css while keeping one layout to maintain.
After going through this it seems nested layouts wouldn't be the best solution to this after all. That's what I love about Monorail...there are a million simple ways of doing what you need without having to play the event-guessing-game as you do in WebForms. Plus, I keep the nitty-gritty view details out of my Controllers and isolate them in their own objects (ie, Filters). Sweet.