Article

Build an XML/XSLT driven Website with .NET

Page: 1 2 3

Create the Web Pages

With the UIEngine done, next is the creation of the Web pages. There are at least two different methods we could use to accomplish this task. The defaut is to create Web Form aspx page and handle the rendering in the Load event. The new class is derived from System.Web.UI.Page and the Load event is handled by a method called Page_Load. In the source code you'll find an example of such a page, author.aspx, although it is disabled and not used.

The method that I use is to implement IHttpHandler. Although I have to write it by hand (no wizard is currently available), the code is simple and it doesn't require multiple source files. In addition, the compiled application is a single DLL: i.e. there are no page (aspx) files.

IHttpHandler interface as part of System.Web namespace and lets you define custom handling of HTTP requests. The interface has one property IsReusable, and one method ProcessRequest. The IsReusable property is set to "true" to allow the object to be reused instead of being created every time is needed. To support session state, IRequiresSessionState has to be implemented as well.

How one would call this handler from a browser? You'll need to map this handler to the incoming URLs. This is done in the Web.Config file:

<system.web>  
...  
 <httpHandlers>  
   <add verb="*" path="*.aspx"    
   type="bookstore.UIHandler,bookstore" />  
 </httpHandlers>  
</system.web>

The 'verb' attribute refers to the HTTP verb: GET POST, etc. Setting the value to '*' allows any verb to be used. The 'type' attribute specifies the handler's class name, complete with namespace, and the second part is the assembly name. Using the .Net wizard, set the assembly name to the name of project -- "bookstore" in this case.

The 'path' attribute is more interesting. One can specified a specific URL such book.aspx, wild card name (*.aspx) or even a path -- books/*.aspx. Using the Website name, the absolute URL in the three cases will look like this:

http://localhost/bookstore/book.aspx  
http://localhost/bookstore/<anyname>.aspx  
http://localhost/bookstore/books/<anyname>.aspx

Note that in the third case, the server path is considered to be bookstore/books and HttpContext.Server.MapPath would map the path accordingly.

The extension aspx is used only because it is already registered with the Web Server. A custom extension can be used, but the Web Server needs to know that ASP.NET will handle such extensions.

The API

The Website has a simple API. There are four resources (or virtual pages) or actions once the extensions are stripped:

  • author.aspx -- displays list of the books sorted by author
  • title.aspx -- displays list of the books sorted by title
  • genre.aspx -- displays list of the books sorted by genre
  • book.aspx -- display full details for the selected book

Each of these URLs takes the UI parameters 'skin' and 'lcid', which are optional. The book.aspx also requires 'id' parameter with the id of the book.

The request is handled in method ProcessRequest. First, the UI parameters are extracted and the requested action is determined:

eng.ExtractUIParameters(ctx);  
string action = eng.ExtractAction(ctx);

Then for each action, the XSLT is determined and the XML data is extracted from the business layer logic. In this sample all the actions use the same XML data, which is implemented in class CBookData.

CBookData bd = new CBookData();  
mydata = bd.GetData(ctx);

The action 'book' takes addition parameter id is extracted and added as parameter to the XSLT transformation. The other cases, such parameters, could be passed to the business logic layer as well.

string id = ctx.Request.QueryString["id"];

Finally the transformation is performed and the HTML page rendered in the user's browser.

eng.Transform(ctx,mydata,stylesheet,arg);

Errors are handled by UIEngine.DisplayError method, which displays all the caught exception's messages in canned HTML.

catch(Exception err)  
{  
  UIEngine.UIEngine.DisplayError(ctx,err.Message);  
}

The error pages can be implemented using a XSLT stylesheets in the same fashion as the main UI.

Source Code and Installation Instructions

The source code is zipped in a file code.zip, which you can download here. There are two C# files UIEngine.cs and UIHandler.cs. The UI is under directory 'UI' and contains two skins -- default and 'dark'. The 'dark' skin is also localized for locale 1026. The data file 'book.xml' is in subdirectory data.

  1. Using VC.NET create new project using the wizard "Visual C# Projects| ASP.NET Web Application". As the name of your project enter "bookstore". You can choose a different name, but you'll need to modify the namespace in UIHandler.cs and the httpHandlers in Web.Config to reflect that name.
  2. Unzip the sourcecode.zip into the local directory of your new project (for example C:\Inetpub\wwwroot\bookstore). There should be two folders, "UI" and "data" in the project's directory.

  3. Add to the project UIEngine.cs and UIHandler.cs using "Project | Add Existing Items" menu.
  4. Optionally, remove WebForm1.aspx created by the wizard.
  5. Open and modify Web.Config file:
  6. <configuration>  
    ...  
       
    <system.web>  
           
    ...    
       <httpHandlers>  
     <add verb="*" path="*.aspx" type="bookstore.UIHandler,bookstore" />  
        </httpHandlers>  
         
    </system.web>  
     
    <appSettings>  
             <add key="ui.base" value="ui\" />  
    </appSettings>  
    </configuration>

  7. Compile the project.
  8. Display the list. In the browser, enter http://localhost/bookstore/author.aspx . The list of the books, sorted by author, should display.

This simple Website harvests the ASP.NET functionality, the entire code is less then 300 lines long, without the UI. The code is readily reusable and the power of XML/XSLT will help you create and maintain dynamic Websites with little effort. For a real site, a production strength database needs to be added. That means designing database schema and database queries, which are very important in ensuring good performance and the scalabilty of the site. Then one would need a module to communicate with the database. ADO.NET is a good choice as an underlying database library. It can handle various databases, it is natively implemented in .NET and it can convert query results in XML format.

Good luck with your site!

This article is part of SitePoint's .NET Feature Guide -- an excellent resource for aspiring and experienced .NET developers. Don't miss it!

If you liked this article, share the love:
Print-Friendly Version Suggest an Article

Sponsored Links

Rate This Article

  • 1
    Poor
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
    Great

Comment on This Article

Have something to say?

Post A Comment

You need to be a member of the SitePoint Forums to comment on this post. Sign Up

Already a member? Post using your SitePoint Forums account: