-
Notifications
You must be signed in to change notification settings - Fork 86
Master Layouts
This entire subject is ASP.NET MVC specific. MonoRail has it's own mechanism for selecting layout files, and Spark works in that context as expected.
When a view is rendered with a master layout template selected Spark renders the view in a multiple passes. The first pass will render the contents of the view template from the top down. The output of that pass is captured in a content variable named view
.
The second pass will render the contents of the master template from the top down. The master template will contain <use content="view"/>
or <use:view/>
at the location where the view content should appear.
<html>
<head>
<title>${Title}</title>
</head>
<body>
<div id="header">dot dot dot</div>
<div id="pageContent"><use content="view"/></div>
<div id="footer">dot dot dot</div>
</body>
</html>
From the master template's perpective the view
is just a piece of named content.
There are several ways to select a which master layout file should be used. The following are the ways a template may be selected, from weakest to strongest.
-
An
Application.spark
file in theViews/Layouts
folder orViews/Shared
folder This is the most general-purpose way to have a site-wide master template. It will not be used if the controller returns aPartialView()
. -
A
.spark
file inViews/Layouts
orViews/Shared
with the same name as the controller For example if you have anAccountController
you could have aViews/Layouts/Account.spark
file which is used on that controller, but all other controllers use theViews/Layouts/Application.spark
template. -
Naming the master layout as the second argument when you return a
View()
as theActionResult
This gives the selection of layout to the controller, which some people may believe isn't necessarily a concern for the controller. What'cha gonna do? If this is present it will override the first two conventions. -
Naming the master layout as an
<use master=""/>
element in the view. This is actually the strongest mechanism available for wrapping a view in a layout file. It will override the conventional forms of master selection, and it will cause the name of the master in theView()
ActionResult
to be ignored if it's present.
Interestingly, it may also be used in the layout files themselves to establish three or more pass rendering.
Three pass rendering can be used to address a common problem. The cause isn't always obvious, especially if you're new to the named-content top-down rendering technique.
The problem is this. Let's say you're using a named content section, like head
or nav
, at the top of your master layout file. Then you add some partials in the sidebar or other places in the layout that add script and stylesheet references to the head
content. The problem you'll encounter is that the head
is actually written to the output stream before those bits further down the layout execute and add those resources to the named content.
<html>
<head>
<use content="head"/>
</head>
<body>
<Header/>
<use content="view"/>
<Sidebar/>
<Footer/>
<use content="tail"/>
</body>
</html>
<content name="head">
<script src="~/content/js/jquery-ui-accordian.js" once="jquery-accordian"></script>
</content>
<div id="sidebar">etc</div>
One way to use three-pass rendering to solve this problem would be to create a super-layout named Html.spark
, and for the master file Application.spark
to wrap itself in that layout. Note that from the Html.spark
file's perspective the entire output of the Application.spark
, and the view which it encloses, is contained in the view
named content.
<html>
<head>
<use content="head"/>
</head>
<body>
<use content="view"/>
<use content="tail"/>
</body>
</html>
<use master="Html"/>
<Header/>
<use content="view"/>
<Sidebar/>
<Footer/>