As you see, on asp.net there's a very long-running discussion going on on an important topic for many web developers: how to create page templates that contain the layout of a webpage and are re-usable for each of your pages. A template must conform to at least the following rules:
1) The template should contain the entire HTML structure, from <html> to </html>, except for the content section of course.
2) Use of separate header and footer templates are reluctantly allowed, but if it's in any way possible the template must consist of one file.
3) The template must be usable by multiple pages (doh).
4) The template file, as well as the page that uses the template, must remain in a format that VisualStudio recognizes, so you can use Design Mode, IntelliSense, etc.
5) The template should contain customizable properties of its own, for example: a PageTitle property that is parsed within the <title> and </title> tags.
There are many ways to do this, but none of them is perfect: from user controls to inheritance, they all cause problems one way or another.
To the Channel 9 guys: how have you templated these C9 pages? What technique do you use? (Do you use templates?
To all other folks: your thoughts on this problem? What pros and cons do you see in the various methods?
(Reading the entire asp.net thread, or at least skimming it, is recommended)
Doesn't the next version (Master Pages) fix this issue?
Largely the debate at ASP.NET is the same debate everywhere: why are we using a templating engine to build a templating engine. The Master Pages feature (if I understand it correctly) will really play into the core templating engine, allowing you to simple extend pages from a single, or set, of inherited pages.
If this works, I'm happy and have nothing further I'd like. Very happy in fact
We do use a templating system. Ours is built based on the Asp.Net Forums 2.0 skinning system. It is a SkinnedForumWebControl similar to the Asp.Net Repeater control. The control is very basic and doesn't meet all of the requirements that you mention, it also doesn't use the methods drawn out in that thread. Rather than having our pages inherit from a base page control, the template itself is a control, which has four ITemplate properties -- HeaderTemplate, RightBarTemplate, ContentTemplate and LeftbarTemplate. The HTML of the control itself looks something like this:
<Forums:Style runat="server" ID="Style1" />
<asp:PlaceHolder id="HeaderControl" runat="server" />
<div class="left" runat="server" id="LeftBarContainer">
<asp:PlaceHolder id="LeftBarControl"" runat="server" />
<div class="content" runat="server" id="ContentContainer">
<asp:PlaceHolder id="ContentControl"" runat="server" />
<div class="right" runat="server" id="RightBarContainer">
<asp:PlaceHolder id="RightBarControl"" runat="server" />
Obviously this is a vast simplification, the actual HTML contains pretty much everything that is common to the entire site. The header image, The Crew, Online Users, the HTML for the footer and both of the main navigation controls at the top of the page.
The PageTemplate class which inherits from SkinnedForumWebControl simply has 4 ITemplate properties and the children of the properties are instantiated in the corresponding PlaceHolder control. The reason for each of the container controls is that we can decide weather or not to show the container depending on the contents of the template, the RightBarControl is invisible when the RightBarTemplate property is null for instance. Once we created this Page template, we just built all of our pages using this as the main control on the page. Our pages end up looking like this:
<Forums:PageTemplate ID="template" Runat="server">
<Forums:ThreadView runat="server" id="ThreadView1" />
The real great parts of this system were all implemented in the Asp.Net Forums 2.0 code, we just added a little sugar to make it taste better. The most difficult problem that we've faced with this method is probably that it isn't possible to access an ITemplates control collection. We'd like to be able to in a code behind do something like:
((Literal)this.template.HeaderTemplate.FindControl( "Title" ))
.Text = "Page Title";
But instead, we are forced to make a control <Forums:Title> which poses a rather difficult state problem, context is difficult to achieve and the page's title logic is not encapsulated in the page itself but rather in a site wide Title control (alas, that's a lie, title is handled in Forums:Style, so goes the difficulty of finding a simple example to represent a complex problem, the concept still holds true however). Aside from that deficiency, this method has treated us quite well. I'm not sure I've done it justice here, but I think you get the idea. Thanks for asking miies, this type of curiosity is my favorite part of this project.
Bryn Waibel wrote:
I'm not sure I've done it justice here, but I think you get the idea.
Yep, I get it. Thanks for the vast explanation
Bryn Waibel wrote:
Thanks for asking miies, this type of curiosity is my favorite part of this project.
No problem. Templating is a subject I've been interested in for years now, in every job and every language/technology I've had to deal with this, as I am a strong supporter of design/content/logic separation. When .NET didn't even exist yet I already built custom templating COMponents, but, as I said, in one way or another, they never solve all problems.
Just like Jeremy said above, I'm curious to see what the MasterPage feature in the next version will be like. I'll read some articles about it after this post.
I have always just done the standard: Inherit Page - Title Property - write beginning html-render-ending html. We don’t use "Design Mode" so I am not sure if that passes #4. I really don’t think with this technique it matters. I read that thread a while back and it seems to me that some template techniques are a bit overkill and may not be that intuitive for other developers who may have to work on your application. I guess it also depends on what kind of application you are building and also the people working with you.
I've written a new reply to the (still running) thread, at:
(Page 14, last post)
Maybe you all will find it interesting to read.
I talked about a similar thing here a week or so ago in "Are Web Controls an Anti-Pattern?" post. I will try and take a different angle here to avoid repetition.
I have a deep philosophical problem with two (well more then two but these will do for a start) aspects of web application development:
1. Using code and markup in the same file,
2. Placing or rendering markup in compiled code.
The reasons are discussed in my previous post but I am always happy to repeat them ...
I only did a quick skim of the post you referenced (14 pages!! someone should write the book) so I don't know how deep the discussion got into front-controllers and MVC. To me this is a far superior solution compared to the current page controller implementation in ASP.Net. Incidentally one of the Microsoft architecture articles states something like that, as the application complexity increases a front-controller implementation should be considered to replace the existing page-controller one.
Over the last 18 months I have been messing around with Maverick.Net (and my own cut down, very unpolished, version MaverickLite). These frameworks allow very complete and clean seperation of the presentation and content layers as well as avoiding the two previously listed pet hates.
A quick hello world example demonstrates better then any explanation.
The heart is a workflow map which can be stored in a file somewhere, the important part is an entry like:
<path value="models/helloWorld.xml" />
Where the web.config has an entry like:
<add verb="*" path="*.aspx" type="MaverickLite.Dispatcher, MaverickLite" />
The flow is:
1. Page request for helloWorld.aspx is received (the helloWorld* is a regular expression so helloWorldA.aspx and helloWorldItsANiceDay.aspx would also get serviced by this entry),
2. A controller is instantiated to build a model. In this case there is a null controller and the model is a simple XML file,
3. The controller instantiates the appropriate view and passes it the model,
4. The view transforms the model and sends the result to the HTTP response stream.
In my view the elegance of the solution is summed up by these features:
1. The content (aka the model), or XML file(s), are produced by OO programmers,
2. The designers produce the transforms (aka the view), or XSL file(s),
3. Steps 1 and 2 can occur in parallel as soon as the XML schema is defined,
4. There is NO script involved,
5. There is NO HTML hard coded or rendered in compiled code.
Despite the fact that I believe the front-controller & MVC approach are far superior to the page-controller one I intially found that it was taking me longer to get the applications up and running. I put this down to familiarity. At the start of the year, after working with the framework for 12 months or so, I did a test on how long it would take to build the IBuySpy site using Maverick.Net (implementation, workflow), it took 20 hours. I suspect this is not much different to the time it would take doing it using a traditional ASP.Net approach? However the big difference would be the maintenance. In the Maverick case all presentation can now safely be handed of to designers!