posted by: Ralf Rottmann | posted @ Sunday, September 16, 2007 5:24 PM | View blog reactions

In the first part of this series I introduced the basic concepts of Subtext skinning which will allow you to accomplish most of the routine tasks required to personalize your blog's look. As said before most design aspects can be achieved by a combination of rearranging custom tags (ASP.NET tags and Subtext tags) in the user controls located in a skin's Controls folder and extensive use of cascading style sheet rules.

While the first part was pretty hands on and there are many great tutorials for topics like CSS and ASP.NET user controls available already, this part will dive a bit deeper into the plumbing and inner workings of Subtext. You don't necessarily need to understand those, to create exciting skins for Subtext, however, I always found it extremely helpful to understand what's going on behind the scenes. At least this provides for a more comfortable feeling when I touch and change parts. It eliminates some of the guessing...

Before we start here is my obligatory note: Currently the official available Subtext documentation is pretty weak. Therefore all of the content I provide in my series is subject to my own research. The ideas I promote might not necessarily be best-practices and chances are that my understanding of Subtext's inner workings might be partially wrong. I encourage all readers to submit their comments to help improve and spread the word!

Prerequisites

To follow along with the contents of this part I'd recommend to download the Subtext solution including the source code. To understand the complete picture we will dive into parts of the Subtext source code. I am currently using Visual Studio 2008 Beta 2 but it is not required to follow my instructions. Feel free to use any other text editor. (The free open source SharpDevelop will be just fine).

Understanding the rendering life-cycle

One of the aspects which many Subtext users who come from a PHP background find difficult is understanding how the final rendering output (the final HTML markup which is send to the browser) gets assembled and which components are involved in the process. This is only partially a Subtext specific issue. It's mainly caused by Microsoft ASP.NET's page request and life-cycle model. Because the ASP.NET way differs quite a bit from those implemented by traditional CGI/scripting solutions like PHP it might take a bit of time until you get familiar with it and recognize it's many great benefits.

Let's get hands on!

While you might have come to my blog through a direct link to any of my Subtext articles, the default location to access this blog is http://www.talentgrouplabs.com/blog/.

Standard ASP.NET looks for a file named default.aspx (not case sensitive) and there is a default.apsx file in the root of your Subtext installation. However, if you open that file you will most likely find default content written by the Subtext project lead Phil Haack and not any placeholders which would be replaced by your blog posts. Welcome to the ASP.NET world!

So what's going on when somebody visits the main URL of a Subtext blog?

The secret is in Web.config (located in your Subtext root directory). First of all, the following line

image

defines DTP.aspx as the default page for your blog. (Note: HandlerConfiguration is not a standard ASP.NET element - it refers to the HandlerConfiguration type in the Subtext.Framework.UrlManager namespace.)

Setting the defaultPageLocation to DTP.aspx defines this file as being the default template for all of your Subtext pages. If you for example would like to add meta tags to every of your blog pages, this is the place you were looking for. Future versions of Subtext might provide a means to set meta tags via the admin control panel - today except for the "author" meta tag you would have to add them manually to the DTP.aspx default template. I added a couple of meta tags to my DTP.aspx:

image

Scroll a bit further down and you might be surprised there's not too much else in the default template. The <body> tag comprises just a couple of lines:

image

The key here is that at runtime the <asp:PlaceHolder> will be replaced by the actual body content. But how does Subtext determine what to replace the placeholder with? Again the answer lays in Web.config. The last <HttpHandler> element in Web.config defines the control which will be used to replace the placeholder if a request for default.aspx is recognized:

image

Subtext will replace the placeholder in DTP.aspx with the contents of the homepage.ascx, another control in the Controls folder of your skin directory. This is a pretty powerful mechanism and Subtext makes a lot of use of it. It also facilitates the ability to further extend Subtext in future releases.

Let's investigate another example: If you navigate to http://www.talentgrouplabs.com/blog/tags/ you will get a full tag cloud of my blog. A quick look into Web.config reveals the control which is used:

image

Control deep diving

Before we move on, let's recap:

DTP.aspx is the default template as defined via the defaultPageLocation attribute of the HandlerConfiguration element in Web.config. While DTP.aspx provides the <head> section of the final document the main contents will be rendered by user controls. The first user control is again configured on a per URL pattern base in Web.config. For the main URL of a Subtext blog (the implicit /default.aspx page) it's the homepage.ascx user control which renders the home page contents.

Open the file HomePage.ascx in your skin's Controls directory. Here's mine:

image

Hmm. Seems as if the HomePage.ascx control is just there to include yet another user control: DayCollection.ascx. Before we look into DayCollection.ascx let's stick for a minute with HomePage.ascx. Looking into the .ascx file does not reveal the full user control story, though. Take a second look and you'll find out that HomePage.ascx extends a base control defined as part of the Subtext system controls:

image

ASP.NET brings object oriented programing concepts to the web world. User controls can be based on other controls, inherit their behavior and extend it. In order to find out the implementation of the base control (Subtext.Web.UI.Controls.HomePage) you do need to download the Subtext distribution including the source code.

If you've opened up the Visual Studio solution file (SubtextSolution.sln) use your IDE of choice to navigate to the Homepage.cs file, which is the C# source code file from which the concrete HomePage.ascx residing in your skin's directory derives. For your convenience here is an excerpt of Homepage.cs:

image 

While the HomePage.ascx seems to just include the DayCollection.ascx user control from this source code snippet you learn that the base user control does some initializing work once the control is loaded (the initialization is hooked to the OnLoad event). Via some helper classes this control finally calls the GetBlogPosts() method to read the posts to be rendered on the homepage from the database.

In the next part of this series we move on with our journey and learn how the DayCollections.ascx with the help of yet some other user controls renders the list of posts. We will learn about ASP.NET Repeaters and understand how they get bound to Subtext content.

Stay tuned!

A remark on Subtext MasterPages

While you investigate Subtext you occasionally might run into the term "Master Page". This can be quite confusing as the concept of Master Pages was officially introduced with ASP.NET version 2.0. The current version (1.9.5) of Subtext does not make use of the ASP.NET 2.0 Master Page concept. In fact the lack of a generic Master Page / Template concept in ASP.NET 1.0 has often been criticized. As Subtext also runs on older versions than ASP.NET 2.0 it implements its own Master Page concept from scratch. (Well, not entirely from scratch but based on Paul Wilson's excellent demo.) So whenever you read about Subtext and Master Pages bear in mind it's not ASP.NET 2.0 Master Pages, yet.

 

comments
No comments posted yet.
post your comment
Title *
Name *
Email
Url
Comment *  
Please add 1 and 8 and type the answer here: