This is a copy of the 2nd article that I wrote concerning the generation of a web site purely from XML content that is transformed into HTML via XSLT.

Here you will see my journey from classic asp to ASP.Net and the streamlining of the director-builder design pattern when there is an object oriented language to support it.

Please note that this was desgned and implemented using VS2003 and .Net 1.1 . I have since refactored and deployed this concept twice for all of my Raritan Valley Community Course websites:
  • Using VS2005 and replacing the builder code with the <asp:XML/> server side tag . By setting the DocumentSource attribute to the path to the xml data content and the TransformSource attribute set to the path of the XSLT transformation the server tag became the Builder.
  • Using VS2010, C#, and the MVC3 framework I moved away from Forms processing to a purer HTML solution.  The contollers for each view set the path for the XML and XSLT content which is then rendered to the client via an HTMLHelper extension method that performs the transformation - thereby the extension method becomes the Builder.

XML and Web Services magazine was eventually taken offline(but I got all the content - except the resources links-  before that happened!) .
I provide it here as a courtesy for my students and prospective clients. Enjoy!

 
 

Infinite Web Pages from One ASP
Generate infinite HTML pages on a single Web site with one ASP rather than two, courtesy of object-oriented features in .Net
by Andrew C. Mayo

Posted April 1, 2003

Two years ago I created a Web site composed of two active server pages (ASPs) that could produce an infinite number of HTML pages (see Resources for a link to the article). I used this technique because I wanted a Web site for my XML course that was scalable, maintainable, and able to showcase XML technology in action for my students. Now, taking advantage of its object-oriented (OO) features, I've recoded that Web site with .Net and ported it to a single ASP.Net page. The technique I used is useful for those who want to unravel the XML transformation aspects of .Net, as well as for those who are interested in using a design pattern that permits creating a scalable Web site with one ASP.Net page containing just three lines of code. This technique also is useful as a piece of a Web site that performs XML-to-HTML transformations as part of its processing.

XML is about data, and the technologies surrounding it can be segregated in three categories: configuration, messaging, and transformation. You can find examples of the flexibility of XML files using application configuration information such as saving user preferences in a Windows application or the web.config file in ASP.Net applications. The messaging/data transport mechanism of XML is found through such technologies as Simple Object Access Protocol (SOAP), Web services, and the disconnected recordset object or data set in the .Net platform. Transformation exists with the Extensible Stylesheet Language Transformation (XSLT) standard, which serves as a means of transforming XML documents into other text-based formats. XML's configuration and transformation categories are the key ingredients for the construction of the Web site example described here. An XML file containing configuration information constructs the site, which is presented to the user through server-side transformations of XML into HTML.

In my first article, I mentioned a similarity between an Internet site diagram and an XML document. Both are hierarchical and depend on a root. Thus, I could structure an HTML Web site using an XML document. Page elements within an XML document represent the pages. The Page element contains attributes that state the page's identification, its name, and whether the page is active. This element has subelements (doc) attached to it that state where the data for the page is located (type="xml") and also where the transformation of that data is located (type="xsl"). The configuration information has this structure:

<Master>
<Page active='Yes' default=
	'Yes' MainMenu='Yes' id="P00" 
	Name="Home">
<doc Type="xml" URL=
	"\xml\home.xml" />
<doc Type="xsl" URL=
	"\xsl\home.xsl" />
</Page>
…
</Master>

A Web site designed in this manner loads this configuration information as soon as the application starts and caches it for use in creating a page requested by a user of the site. The Web site also uses the information in this configuration file to create a common menu that displays on each page of the Web site. The common menu is a result of the transformation of the configuration file from XML to HTML, and it's also cached by the application.

In a nutshell, whenever a user requests a Web page, the application interprets the configuration information to find the requested page. If it's found, and if it's active, it then uses the doc subelements to locate the content for the page (type="XML") and the transformation instructions (type="XSL") of that content. These pieces, data and transformation, are combined through an XSLT transformation to create an HTML page that is output to the user.

The Pattern
Because the process of finding, gathering, and creating an HTML page is a discrete process, it can be accomplished by a preexisting OO design pattern. The pattern is called Director-Builder. The Director gathers the metadata and directs the Builder to build. In our example, the Director verifies that the page exists and is available and then supplies that information to a Builder that builds an HTML page. The information supplied to the Builder is the data, or content, and the presentation/transformation instructions.

 
Figure 1. Original ASP Implementation.

At the time that I developed this concept, ASP was the Internet programming vehicle of choice for anyone programming Internet applications for the Microsoft platform. When I applied this pattern to ASP, since ASP was not object-oriented, I had no choice but to create a site that contained two ASPs that communicated with each other through session variables and query strings. The main page is Director.asp, which performs a Response.redirect to the Builder.asp, which in turn outputs the HTML transformation result (see Figure 1). This site is scalable; because of the design pattern and the configuration structure, any site can be deployed using the same code, and all that needs changing is the site diagram and its corresponding data/transformation content. Because of the inherent limitations of ASP, namely the inability of code reuse and VBScript as the programming language, the site could not be architected as I had intended. To perform transformations programmatically, you need to use the COM version installed on the server, you can get different results based on the parsers' support of the XSLT standard. This parser also requires DOM objects as both input and output for XSLT transformations.

 
Figure 2. ASP.Net Implementation.

One of the great things about the .Net platform is its support of OO programming. By porting the application to ASP.Net, you no longer need two ASPs or session variables for communication because you can create a Director object and have it perform the work through a single method call (see Figure 2). Since the syntax between VBScript and Visual Basic .Net is both similar and different, the port is not a direct copy of code. For my site I had to re-architect the system by creating base classes and specialized classes to perform the same functionality, which was a good thing, because this code is now reusable and easier to maintain. Under the ASP/VBScript architecture, the most reuse that you can get is from a server-side include file, and then that code can be reused only within an ASP/VBScript application and not across applications. The Director-Builder class structure provides a visual representation of these definitions (see Figure 3).

 
Figure 3. Director-Builder Class Structure.

XMLTransformer
The major difference between .Net and the ASP/VBScript implementation is that transformations are now performed differently; that is, to perform a transformation in VBScript, a COM solution is used with the MSXML parser. The COM version of the XML parser, or MSXML.dll, is a DOM object that performs the transformation in one of several method calls, depending on your preference and need. Conversely, the .Net platform elegantly segregates the pieces of XML functionality into separate namespaces. Specifically, the transformation functionality is placed into its own namespace (system.xml.xsl) and its own object within that namespace (xsltransform) and has full support of the XSLT standard. The XslTransform object has been generalized so that any object supporting the IXPathNavigable interface can be transformed. It has also been optimized through the ability to transform to streams, XMLWriter, TextWriter, String URL, or the XMLReader class.

Because my site depends on XML transformations, I created a custom XML transformation object that encapsulated the functionality of system.xml.xsl.xsltransform. Therefore, the XMLTransformer class performs an XML transformation using string arguments, or XMLReader objects, each of which contains the XML and XSLT instructions, respectively. I also included custom error handling in this object that was capable of generating either a Windows or Web-based error message and, therefore, didn't tightly couple the transformation process to this application—namely, HTML transformation. The XMLTranformer class is useful to either Windows- or Internet-based applications that need to transform XML using XSLT.

With the XMLTransformer in hand, I next needed to create a class that contains functionality specific to this application: the Builder pattern. The HTMLBuilder class is a subclass of the XMLTransformer object and delegates XSLT transformation to its parent, thereby reusing its transformation and error-handling code. This class implements the methods outlined for the pattern and overloaded Build function as well as a GetResults property that retrieves the results of the Build. Any Web site using this code would probably customize the common header output; therefore, I added an interface to the class called ICustomHeader. The purpose of this interface is to add any customized information to the transformed HTML that will contain the common header for the Web site. In this case I use it to navigate to the page element and replace it with the name of the page being displayed. I made it an interface so that it could be implemented easily in a different way by anyone wishing to reuse this code in a Web site designed in this fashion.

I also created a base class for the Director functionality and named it HTMLDirectorBase. It contains the Constructors specific to building a Director class, as outlined in the Design Pattern. This class has a single constructor that accepts an instance of System.Web.UI.Page, which is intended to be the ASP.Net page that creates it (Default.aspx). With an instance of the creating page, this class and any of its subclasses now has access to the rich set of features supplied by the ASP.Net platform (caching, session variables, global variables, and so on), as well as the familiar and faithful Response.Write method. The class also contains one member function called Direct that takes a string argument containing the page to be built. This design allows us to have just three lines of code in the ASP.Net page to produce the Web site:

Dim m_HTMLDirector As New 
	HTMLDirector(Me)

'Create output a page based on the 
	querystring
	m_HTMLDirector.Direct(CStr(
		Request.QueryString("id")))

	m_HTMLDirector = Nothing

HTMLDirector—a subclass of HTMLDirectorBase that overloads the Constructor and the Direct method—is a specialized class specific to the Web site. It is responsible for validating and assembling the metadata for the HTMLBuilder, as outlined in the sequence diagram (see Figure 4). If no page is requested, it defaults to the page that is designated as Main in the Web site configuration file. If a page is requested and it is valid (it exists and it's available), the metadata for the Page (its data and presentation) are dispatched to the HTMLBuilder object for Building (see Listing 1).

 
Figure 4. Sequence Diagram HTMLDirector.

Develop a Menu
You can cache the common header for the Web site in the ASP/VBScript solution through a lot of custom code. Because the site map is in the Master.xml file, any change made to it affects the functioning of the Web site. The same is also true for Master.xsl, which takes the contents of Master.xml and transforms it into the common menu for the system. As you can see, any change to either of these files also causes a rebuild of the common menu, as the main menu could be rendered or pages added to or deleted from the site.

With this system requirement in mind, the original ASP/VBScript solution keeps track of changes by caching the create and modify time stamps for the configuration file (Master.XML ) and the transformation file (Master.xsl). The create and modify timestamps are derived through the COM-based filesystem object and obtained whenever the application starts or a new user session is created. If the create and modify timestamps for either file change, the Master.xml and Master.xsl files are reached, rebuilt, and the common menu is recached.

The legacy code didn't have to be ported, thanks to the ASP.Net caching object (System.Web.Caching.Cache), which is part of the plumbing that has been incorporated into ASP.Net to make developers' lives easier. With the dependency on changes to an underlying set of files, instead of rewriting the legacy code to detect a file change, I created an entry in the cache that was dependant on a set of files. The cache object determines if the files have changed and, if so, sets the value of the cache to Nothing. (See Resources for more information about the caching object in ASP.Net.) When the named cache object is Nothing, we recreate the dependant information (see Listing 2).

Beyond all of the neat and cool things that you can do with ASP.Net—security, server-side controls, custom user controls, field editing and validation, page caching, application tracing, and debugging, to name a few—the object-oriented capabilities of .Net allow you to use design patterns and reusable code to create robust solutions. It is these frameworks that will allow you to go beyond the RAD capabilities of ASP.Net to create elegant, reusable frameworks for any .Net platform applications that you deploy.

About the Author
Andrew C. Mayo is an adjunct professor at Raritan Valley Community College in New Jersey, where he teaches a course on XML. He is the principal of Carlton Software Solutions Inc., a New Jersey-based information technology consulting company, where he specializes in delivering custom software applications using XML and the .Net platform. Reach Andrew at XMLProfessor@CarltonSolutions.com.