Background
After writing and modifying a number of Classic ASP websites, I became very tired of dealing with the lack of separation of business rules and presentation that is inherent in Classic ASP programming. I wrote KudzuASP to address this issue.
Introduction
In this article, we're going to explore the use of the KudzuASP template engine. KudzuASP is a template engine for Classic ASP that is designed to simplify the building of websites by separating business rules and logic from your presentation layer. It accomplishes this by moving as much HTML as possible to template files.
Using the Code
If you've ever coded a web page in Classic ASP, you probably know how frustrating it can be to manage the code that performs the output of your presentation to the client browser. Once you implement business rules and logic combined with program control, data and HTML presentation, it can get messy very quickly. Even very well-organized code at the bottom of ASP pages looks messy. It is a fact that this is the least maintainable part of the application. Changing the look and feel of an ASP application beyond the scope of CSS can be quite a nightmare!
I'll show you one way to clean up those ASP code pages and change the look and feel of your sites more easily than you would imagine. This is done using tagged HTML documents as templates, along with the KudzuASP template engine. Let's jump right into the heart of the matter by exploring three very basic examples. The first example includes the template engine and processes a very simple file-based template.
Example 1: HTML Template
<html>
<head>
<title>KudzuASP Example 1</title>
</head>
<body>
<div>
Hello World!
</div>
</body>
</html>
Example 1: ASP Page
<%
'------------------------------------------------------------
' Declare the template engine variable
'------------------------------------------------------------
Dim T_ENGINE
'------------------------------------------------------------
' Create an instance of the template engine
'------------------------------------------------------------
Set T_ENGINE = New CTemplateEngine
'------------------------------------------------------------
' Load the template and Create Output
'------------------------------------------------------------
T_ENGINE.ParseFile Server.MapPath("Example1.html")
T_ENGINE.EvalTemplate
%>
Well, we got back exactly what we put into our template, which in this case wasn't very impressive. Let's add our very first template directives and perform some substitution within the template.
Example 2: HTML Template
<html>
<head>
<!--
<title>{{PageTitle}}: {{PageSubTitle}}</title>
<!--
</head>
<body>
<div>
<!--Welcome {{UserFName}} {{UserLName}}!<!--<br />
It is now: <!--
</div>
</body>
</html>
Example 2: ASP Page
<%
'------------------------------------------------------------
' Declare the template engine variable
'------------------------------------------------------------
Dim T_ENGINE
'------------------------------------------------------------
' Create an instance of the template engine
'------------------------------------------------------------
Set T_ENGINE = New CTemplateEngine
'------------------------------------------------------------
' Your Code Here
'------------------------------------------------------------
T_ENGINE.PutValue "PageTitle", "Kudzu"
T_ENGINE.PutValue "PageSubTitle", "Example 2"
T_ENGINE.PutValue "UserFName", "Joe"
T_ENGINE.PutValue "UserLName", "Client"
T_ENGINE.PutValue "PageDate", Now( )
'------------------------------------------------------------
' Load the template and Create Ouput
'------------------------------------------------------------
T_ENGINE.ParseFile Server.MapPath("Example2.html")
T_ENGINE.EvalTemplate
%>
First, note that KudzuASP uses component tags and that there are three types of tags:
<!--[Cmd]-->
is the open component tag and it marks the start of component content. It must be matched by a close component tag of the same name. <!--[/Cmd]-->
is the close component tag and it marks the end of component content. It must be matched to a corresponding open component tag of the same name. <!--[Cmd/]-->
is the simple component notation and it is used for components like Replace
that ignore any content within Open
and Close
tags.
The tag's Cmd
value indicates which component you are invoking; it is case insensitive. The component must be registered with the engine. Many components accept parameters and they are passed to the component by adding them as a pipe-delimited list like so:
<--[Cmd|Param1|Param2|Param3]-->
...<!--[/Cmd]-->
...or in some cases:
<!--[Cmd|Param1|Param2|Param3/]-->
This example uses the Substitute
component <!--[Subst]-->
, which replaces all fields marked by {{ }}
tags with values from the template engine's Values
collection. Each value's name is derived by stripping off the {{
and }}
, trimming it and using the result as a case-insensitive lookup into the engine's value collection. You can also look up values from the server, application, session, form post, query string or cookie. More on that will follow in another article.
Example 2 also invokes the Replace
component, <!--[Replace|PageDate/]-->
. Unlike Substitute
, this component requires the value's name to be passed as a parameter. The resulting value is then used in place of the entire tag and its content. We could well have written this as:
<!--[Replace|PageDate]-->
My Page Date<!--[/Replace]-->
...but since we are replacing everything, it makes sense to use the simple tag notation instead.
KudzuASP is Free!
KudzuASP is distributed under the Mozilla Public License.
KudzuASP has 24 Useful Stock Components
There are currently 24 stock components in KudzuASP with the following commands:
Case
: a SELECT...CASE
programming construct based upon a named value CrLf
: inserts one or more Carriage Return Linefeed pairs to HTML output Cycle
: cycles a variable through a series of values (used in iteration) Decr
: decrements a named value Execute
: executes another ASP page and inserts the content into the stream Flush
: flushes the output (implicitly invoked with Execute
) ForArray
: iterates content over an array of values ForEach
: iterates content over a collection of values IIf
: includes content when a named value is true
If
: an If...Then...Else
construct IfTrue
: includes content when a values is true
IfFalse
: includes content if a value is false
Ignore
: ignores the content completely (for prototyping) Incr
: increments a numeric value by one Iterate
: iterates using a named iterator assigned to the iterators collection Record
: evaluates and copies the enclosed content to a named value Replace
: replaces the content with a single named value Profiler
: computes the "end time," sets the named value and evaluates the content SetValue
: sets a named value with another value Space
: inserts one or more spaces into the output stream Subst
: performs multiple substitutions on the content Tab
: inserts one or more tab characters into the output stream Tree
: draws a tree of information using a named value that is of type TreeNode
UnSetValue
: removes a value from the Values
collection
Other Points of Interest
KudzuASP uses VBScript classes to implement components, so it is very easy to extend the template engine to perform any type operation you want. Also, given the manner in which ASP compiles pages, your components can access VBScript's runtime scope -- global variables, application, session, functions and subroutines -- without using Eval(...)
. Because KudzuASP can interface directly into the functions and subroutines you already have, it is very easy to install KudzuASP into existing applications. This is done by creating a custom component that invokes an existing VBScript subroutine or function. For example:
<%
'------------------------------------------------------------
' Declare the template engine variable
'------------------------------------------------------------
Dim T_ENGINE
'------------------------------------------------------------
' Create an instance of the template engine
'------------------------------------------------------------
Set T_ENGINE = New CTemplateEngine
'------------------------------------------------------------
' Your Code Here
'------------------------------------------------------------
Class CallMyCodeComponent
Sub HandleTag( vNode )
' Important if writing HTML directly to the response.
vNode.Engine.ContentFlush
' call the existing subroutine
Call MyExistingSub
End Sub
End Class
'------------------------------------------------------------
' Existing website code
'------------------------------------------------------------
Sub MyExistingSub
Response.Write "<br />"
Response.Write "<b>Hello from the custom component!</b>"
Response.Write "<br />"
End Sub
T_ENGINE.SetHandler "CallMyCode", New CallMyCodeComponent
T_ENGINE.PutValue "PageTitle", "Kudzu"
T_ENGINE.PutValue "PageSubTitle", "Example 3"
T_ENGINE.PutValue "UserFName", "Joe"
T_ENGINE.PutValue "UserLName", "Client"
T_ENGINE.PutValue "PageDate", Now( )
'------------------------------------------------------------
' Load the template and Create Ouput
'------------------------------------------------------------
T_ENGINE.ParseFile Server.MapPath("Example2.html")
T_ENGINE.EvalTemplate
%>
The template for this would look something like the following:
Example 3: HTML Template
<html>
<head>
<!--
<title>{{PageTitle}}: {{PageSubTitle}}</title>
<!--
</head>
<body>
<div>
Templated Based Content
</div>
<!--
</body>
</html>
Note that by simply editing the template and moving things around, we can modify when and where VBScript source code is invoked and thereby alter the location of the resulting output.
Conclusion
That's it for now. You now have everything you need to write fully templated webpages in Classic ASP. Originally, I had planned to write an additional article on the ForEach and Iterate tags but I never did. The reason is that it's much easier to write custom components just like Example 3 does. I hope you've enjoyed my first article here at Code Project, thanks for reading!
Github Repository
The KudzuASP project is currently hosted on Github. Use the following link to the project.
https://github.com/Mumpitz/KudzuASP
History
- 11th December, 2007 -- Original version posted