Programmer to ProgrammerTM  
Wrox Press Ltd  
   
  Search ASPToday Living Book ASPToday Living Book
Index Full Text
 
ASPToday Home
 
 
Home HOME
Site Map SITE MAP
Index INDEX
Full-text search SEARCH
Forum FORUM
Feedback FEEDBACK
Advertise with us ADVERTISE
Subscribe SUBSCRIBE
Bullet LOG OFF
                         
      The ASPToday Article
August 3, 2000
      Previous article -
August 2, 2000
  Next article -
August 4, 2000
 
   
   
   
Enhance Input Forms Using XML   Chris Knowles  
by Chris Knowles
 
CATEGORY:  XML/Data Transfer  
ARTICLE TYPE: Overview Reader Comments
   
    ABSTRACT  
 
Article Rating
 
   Useful
  
   Innovative
  
   Informative
  
 184 responses

Web forms can be a necessary evil. An integral component in many a web site, they are tedious and often time-consuming to code. In this article, Chris Knowles takes a look at HTML forms, identifing their shortcomings and discovering that by judicious use of XML, it is possible to build form–handlers of virtually unlimited sophistication.

   
                   
    Article Discussion   Rate this article   Related Links   Index Entries  
   
 
    ARTICLE

Web forms are a necessary evil. An integral component in many a web site, they are tedious and often time-consuming to code. In this article, we will take a look at HTML forms, identify their shortcomings and discover that by judicious use of XML, it is possible to build form–handlers of virtually unlimited sophistication.

But what’s wrong with HTML-based forms?

Take a look at the following form:

It is a fairly simple form allowing the visitor to provide some basic details about themselves, giving a preference for how they wish to be contacted, describing what they are interested in and the ability to add some extra comments.

In addition to basic validation, the form has other requirements:

So what’s so wrong with this approach?

HTML forms suffer from four major drawbacks:

  1. Merging of function and style

Whilst all HTML documents suffer the drawback of mixing content with style, the problem is especially acute with HTML forms. When we build a form, not only are we providing a basic description of the fields in the form i.e. text box, drop down list, but we are also describing the format and layout.

And often, when embedding a form in ASP we just make the situation worse by adding processing as well: For example, when coding the contact date field, we use code along the lines of:

<TR><TD><FONT face="verdana" size="2" color="black">Contact Date</FONT></TD>
<TD><INPUT type="text" size="8" name="ContactDate" value="<%=strContactDate%>"</TD></TR>

The drop down box becomes something like:

<select name="Interests">
<% Set objRS = objConnection.Execute ("SELECT * FROM Interests")
  
  While NOT objRS.EOF
%> <option value="<%=objRS("Interest")%>"><%=objRS("Interest")%></option>
<%   objRS.moveNext
  Wend
   objRS.Close
   Set objRS = Nothing%>
</select>

Through no fault of our own, the form is already unwieldy: a tangle of formatting tags and form definition tags, all of which often makes debugging and maintenance a massive headache.

  1. Form definition extremely basic

When we define our forms the tags we can use are very basic. Sure, we can describe what type of field it is and how long it is, but that’s about it. We cannot give any basic validation information about a field, nor can we make the provision of one field dependent on the input of another. For example, how do we ensure that the email address is validated as an email address and not a simple text field and that if the visitor chooses to be contacted at home, that they have completed the contact home field?

Certainly, several less than elegant solutions to our first validation problem are provided in the pages of any ASP book worth its salt. In the ubiquitous chapter on HTML forms there’ll be a generic form validator using either hidden fields to store validation information or field name extensions to trigger validation.

How do these work? Suppose we are trying to code the relevant entry to ensure that the contact email address is entered and is a valid email address. Our hidden fields based validator adds INPUT tags for each test, so coding for the email address scenario would produce something akin to the following:

<TR><TD><FONT face="verdana" size="2" color="black">Test Form Field</FONT></TD>
<TD><INPUT type="hidden" name="type" value="email">
<INPUT type="hidden" name="required" value="yes">
<INPUT type="text" name="ContactEmail" size="20"></TD></TR>

This would only exasperate our spaghetti code dilemma as now we have three INPUT tags for a single entry:

Using the field name extensions validator is neater. By adding a tag for the field type and one for whether the field is required, we can automatically trigger some validation with a single INPUT . However, that name is growing in length, we have to do a lot of parsing of the field name to find out what validation is required and the number of options you can code on a name is limited:

<TR><TD><FONT face="verdana" size="2" color="black">Test Form Field</FONT></TD>
<TD><INPUT type="text" size="50" name="ContactEmail_email_req"></TD></TR>
  1. Almost impossible to reuse

All programmers hate to do things twice and are constantly looking for ways to write generic code and reuse it as many times as possible. All our sites use forms, often very similar forms and yet they are virtually impossible to reuse without modification.

Why? Because that formatting is mixed with the form definition which is mixed with the processing. Unless our two sites have identical layouts then we are probably going to need to do some modifications.

  1. No flexibility

If we look at a form’s "life cycle" we can see that HTML forms offer the ASP programmer very little assistance. We already know how inflexible they are in validation, but what about pre and post validation processing?

Presetting the form field values

HTML forms have virtually no presetting capability, for example, setting the contact date to the current date. I say virtually no, because our hidden field based validator could do it, but we would end up with something like this:

<TR><TD><FONT face="verdana" size="2" color="black">Test Form Field</FONT></TD>
<TD><INPUT type="hidden" name="type" value="email">
<INPUT type="hidden" name="required" value="yes"
<INPUT type="hidden" name="initialvalue" value="todaysdate"
<INPUT type="text" size="20"></TD></TR>

Our validator could check for the initial value and set the field accordingly, but our list of hidden fields is growing out of control.

And what about our drop–down box for possible areas of interest? Not possible with our name extensions validator, so yet more hidden fields to specify table names and fields.

Pre-validation processing

After our form is validated, we are going to want to use the form data, probably to send in an email or to update a database table. With our hidden fields validator we are left with an enormous collection of values in the Request object of which we are only interested in a fraction. Our name extension validator leaves us with a collection of awkwardly named fields that will need processing before we can do anything with them.

XML based forms – A new approach

(If you are new to XML you’ll probably want to learn more. Microsoft’s MSDN web site has a dedicated XML area, http://msdn.microsoft.com/xml?WROXEMPTOKEN=1582872ZfuLqf1zNHlx5hq8yrf. Download the XML SDK which includes an XML parser and a comprehensive help file, including tutorials. Otherwise, you might want to try http://www.xml.com/?WROXEMPTOKEN=1582872ZfuLqf1zNHlx5hq8yrf, or IE5 XML by Alex Homer, Wrox Press).

Using an XML document to store our form definition constitutes a new approach to form processing. The XML document drives all form processing; initialization, validation, display, error reporting and post validation processing. It is important to recognize that we are not replacing HTML forms with XML based forms: an HTML form is still the final output but is only there to provide the user with an interface to enter the data.

It is also important to remember that none of the processing described below is inherent in an XML document. The benefits come from creating a form handler that can read and understand the definition. After all, an XML document is just a collection of ASCII characters with no inherent meaning until utilized by an application that understands just what the elements and attributes mean.

So, what do we gain by using XML for our form definition?

Separation of formatting, content and functionality

Whilst XML’s use as a platform–independent information exchange format is much heralded, arguably the greatest benefit that XML brings to web site development is the ability to split format from content and functionality.

Stored in XML, our source documents become free of HTML formatting and are therefore easily ported across sites. Need the same form in another site? No problem, just create a new stylesheet and leave the form definition alone. Revamping a web site? No problem, leave the content alone and just amend the stylesheets.

Infinite tags means infinite possibilities

With XML we define our own schema, that is our elements and attributes. We can therefore create an XML document that describes our form so completely that our form handler can handle almost situation.

For example, we want to define a form field that is a date field, we want the text preceding the form (the label) to read "test date", we want to ensure that the field is entered and we want it initialized to the current date. Our form field element may look something like this:

<FIELD type="date" label="Test Field" initialvalue="today" required="yes" />

Of course, we can create far more complex fields. Suppose we want to define a drop down box, the options of which will be built from a database table. We also want to define which table field becomes the value and which table field is displayed in the drop down box:

<FIELD type="select" label="Test Drop Down Box" required="yes">
   <LOOKUP table="Test" valuefield="ShortField" displayfield="LongField" />
</FIELD>

We have created another element, LOOKUP , to describe the table and the field information and because it is relevant only to this FIELD , it is inserted between the open and close tags.

Any situation can be catered for with appropriate tags and attributes making our form processing incredibly flexible.

Dynamic manipulation of form during processing

Through the XML parser, your XML based form exposes a multitude of properties and methods that enable us to manipulate the form during processing.

For example, when the form is first loaded there may be some initializing of fields, such as the date and drop down box example in the previous section. These values are added to the XML document during the presetting phase. Our date field would become:

<FIELD type="date" label="Test Field" initialvalue="today" value="01/01/2000" required="yes">

During validation, we will want to tag a field in error; so we will add an error attribute. We then also have the option of adding an error message on the field, or creating a new element altogether. Which option you choose will depend on how you want to display your error messages but tagging the FIELD with an error tag at least allows us to change the color of the label or add an "*" at the end of the input box to indicate that the field is in error.

The XML document allows us to add and remove elements and attributes as we see fit. This allows for incredibly flexible functionality and much more user–friendly output. Having all the form information in an XML document also benefits post–validation processing. As you start writing components that use XML documents for their input parameters, form output can be easily transformed into a format suitable for input to the next process.

Superior validation capabilities

By using XML we can greatly enhance the validation of the form. On a field basis, we can make a type attribute identify a field as text, number, telephone, zip code, currency, credit card, date and email address, etc. The list is literally endless. We can also tag the field as required, set minimum and maximum values or identify a database table against which any input should be checked.

Perhaps even more intriguing is the possibility of validating against relationships. By grouping fields together, we can, for example, ensure that only one option is chosen. If we want to have a user enter only one contact phone number, we could use the following elements:

<FIELDSET mininput="1" maxinput="1" required="yes" label="Contact me on : ">
  <FIELD type="telephone" length="16" name="HomePhone" />
  <FIELD type="telephone" length="16" name="WorkPhone" />
  <FIELD type="telephone" length="16" name="MobilePhone" />
</FIELDSET>

Or we could make the input of one field dependent on the value of another – e.g. if the user enters an age of less than 18, then make sure they also entered the name of a parent or guardian:

<FIELD type="age" length="3" name="YourAge" />
<FIELD type="text" length="30" name="GuardianName" dependson="YourAge" dependscheck="&lt; 18" />

Summary

As we can see, the benefits of basing your forms in XML rather than HTML are enormous: portability, flexibility and the potential to use a single code component to handle almost any form’s processing. But the XML document is only one component of the process.

The XML-based form handler

Hopefully, your appetite for XML based forms is whetted and you are ready to try some sample code to see how it could all work. Don’t forget, this is my personal schema and I am sure that you will want to change and enhance it.

Overview

The form handler uses an XML file to hold the form definition, an XSL stylesheet to translate the XML form to HTML for displaying in a web browser, and ASP to control the form processing and the HTML translation and the Request.Form collection for the form values.

The form handler has been kept fairly simple but will still demonstrate:

The XML Form

Here is the XML document for our example form:

<?xml version="1.0"?>
<FORM name="form">
  <!-- name -->
  <FIELDSET label="Name Details">
    <FIELD id="1" type="text" name="firstName" size="30" req="yes" label="First Name"/>
    <FIELD id="2" type="text" name="lastName" size="30" req="yes" label="Last Name"/>
  </FIELDSET>
  <FIELD id="3" type="email" name="email" size="50" req="yes" label="Email Address"/>
  <!-- preferred contact -->
  <FIELDSET min="2" max="2" req="yes" label="Preferred Contact Details">
    <FIELDSET min="1" max="1" req="yes" label="Select preferred number">
      <FIELDSET min="2" max="2" label="At Work">
        <FIELD id="4" type="radio" name="contactPlace" value="work" label="At Work"/>
        <FIELD id="5" type="telephone" name="workNumber" size="15" label="Work Number"/>
      </FIELDSET>
      <FIELDSET min="2" max="2" label="At Home">
        <FIELD id="6" type="radio" name="contactPlace" value="home" label="At Home"/>
        <FIELD id="7" type="telephone" name="homeNumber" size="15" label="Home number"/>
      </FIELDSET>
    <FIELDSET min="2" max="2" label="On Mobile">
        <FIELD id="8" type="radio" name="contactPlace" value="mobile" label="On Mobile"/>
        <FIELD id="9" type="telephone" name="mobileNumber" size="15" label="Mobile number"/>
      </FIELDSET>
    </FIELDSET>   
    <FIELDSET min="2" max="2" label="Contact Date and Time">
      <FIELD id="10" type="date" name="whenDate" size="8" initial="today" label="Date"/>
      <FIELD id="11" type="time" name="after" size="5" initial="now" label="After"/>
    </FIELDSET>
  </FIELDSET>
  <!-- area of interest -->
  <FIELD id="12" type="select" name="areaOfInterest" label="Area Of Interest">
    <LOOKUP connection="testing" table="areaOfInterest" display="description" value="description"/>
  </FIELD>
  <!-- comments -->
  <FIELD id="13" type="textarea" name="comments" label="Comments"/>
</FORM>

This example uses a fairly simple structure, with three major elements FORM , FIELDSET and FIELD .

The FIELD element is the building block of the form and is the rough equivalent of the HTML INPUT element. It can have the expected attributes of id, type (review the function validInput to see what types are available), name , size , value , label and initial . I have included id so that a FIELD can be uniquely identified, which is a great help when building stylesheets containing radio buttons that share a common name.

The form handler included in this article only converts the parameters today (current date) and now (current time): anything else is assumed to be literal text (which is the equivalent to coding a value attribute). If req is set to yes , then the FIELD is mandatory input.

The LOOKUP element is a child element of FIELD and is used to build a selection list from a database table. To hardcode a selection list replace LOOKUP with OPTION elements.

The FIELDSET elements group FIELD and other FIELDSET elements to allow validation of relationships by using the min, max and req attributes. For example, the following XML snippet ensures that if the visitor enters a home number if they choose the At home radio button:

<FIELDSET min="2" max="2" label="At Home">
   <FIELD id="6" type="radio" name="contactPlace" value="home" label="At Home"/>
   <FIELD id="7" type="telephone" name="homeNumber" size="15" label="Home number"/>
</FIELDSET>

To restrict the visitor to choosing only one of At Home , At Work and On Mobile :

<FIELDSET min="1" max="1" req="yes" label="Select preferred number">
  <FIELDSET min="2" max="2" label="At Work">
    <FIELD id="4" type="radio" name="contactPlace" value="work" label="At Work"/>
    <FIELD id="5" type="telephone" name="workNumber" size="15" label="Work Number"/>
  </FIELDSET>
  <FIELDSET min="2" max="2" label="At Home">
    <FIELD id="6" type="radio" name="contactPlace" value="home" label="At Home"/>
    <FIELD id="7" type="telephone" name="homeNumber" size="15" label="Home number"/>
  </FIELDSET>
  <FIELDSET min="2" max="2" label="On Mobile">
    <FIELD id="8" type="radio" name="contactPlace" value="mobile" label="On Mobile"/>
    <FIELD id="9" type="telephone" name="mobileNumber" size="15" label="Mobile number"/>
  </FIELDSET>
</FIELDSET>

If req is set to yes on a FIELDSET then the min and max requirements must be met. If req is set to no or not present then no fields need to be entered for the FIELDSET . In the above example, only one option can be entered so the req attribute can’t be set on the child options. Setting it on the parent FIELDSET , though, ensures that the min and max are met, in this case requiring that one and only one of the options are entered.

The original form definition can be extensively changed by the form handler. The form is expanded during pre–loading processing to include any look–up table data and initial field values and during validation, all errors are added to the form.

XSL stylesheet

The XSL stylesheet converts the form to HTML format for displaying in web browsers and handles building the form and outputting any error messages. The stylesheet included with this article has been coded specifically for this form: it is easier to do this than trying to come up with an all encompassing stylesheet, although you will find that many of the templates will be the same from form to form.

In the example, the stylesheet only produces a partial HTML file. This makes it easier to include the form handler in your own applications.

ASP

The ASP drives the process. The form handler code itself has been bundled up into an include file for easy insertion. A better solution, beyond the scope of this article, would be to create a form component. The shell ASP shows how simple it is to include the form handler in your applications.

Request.Form collection

Unlike the HTML form validators that use the Form collection to drive the validation process, in the form handler the collection is used to pass the form values to the form handler as the XML document drives the form processing.

The Processing

By checking the Form collection in the Response object the form handler determines whether it should be loading or validating the form.

Loading the form

To load the form, the XML document is loaded into an XML object and then checked for any initial attributes and LOOKUP elements which are processed accordingly. The expanded XML document is then semi–persisted (it is only written after pre–loading and not every time the form is validated) by saving it to a text file on the server. This prevents the handler having to reprocess the LOOKUP elements before validation.

The semi–persisted file is deleted after the form is successfully validated or replaced if another form is requested. Persisted forms will be "left behind" if a user leaves a form without completing it, so it would be prudent to add some processing to the Session_OnEnd subroutine in your GLOBAL.ASA to delete any temporary forms for the session.

The XML document is then translated to HTML using the stylesheet specified in the shell ASP.

Validating the form

To validate the form, the handler reloads the semi–persisted XML document. By recursively calling the validateFieldSet function, it walks down the document validating all the FIELDSET and FIELD elements by checking the value held in the Form collection against the criteria on the FIELD element and then the FIELD elements’ relationships as determined by the FIELDSET attributes.

Any errors encountered during validation are written as new elements to the XML document. A parameter is passed back to main routine indicating the success or otherwise of the validation.

Here is the XML output for the example form with errors:

<FORM name="form" status="error">

  <!-- name -->
  <FIELDSET label="Name Details">
    <FIELD id="1" type="text" name="firstName" size="30" req="yes" label="First Name" error="yes"/>
    <FIELD id="2" type="text" name="lastName" size="30" req="yes" label="Last Name" error="yes"/>
  </FIELDSET>
  <FIELD id="3" type="email" name="email" size="50" req="yes" label="Email Address" error="yes"/>

  <!-- preferred contact -->
  <FIELDSET min="2" max="2" req="yes" label="Preferred Contact Details">
    <FIELDSET min="1" max="1" req="yes" label="Select preferred number" error="yes">
      <FIELDSET min="2" max="2" label="At Work">
        <FIELD id="4" type="radio" name="contactPlace" value="work"  label="At Work"/>
        <FIELD id="5" type="telephone" name="workNumber" size="15" label="Work Number"/>
      </FIELDSET>
      <FIELDSET min="2" max="2" label="At Home">
        <FIELD id="6" type="radio" name="contactPlace" value="home" label="At Home"/>
        <FIELD id="7" type="telephone" name="homeNumber" size="15" label="Home number"/>
      </FIELDSET>
      <FIELDSET min="2" max="2" label="On Mobile">
        <FIELD id="8" type="radio" name="contactPlace" value="mobile" label="On Mobile"/>
        <FIELD id="9" type="telephone" name="mobileNumber" size="15" label="Mobile number"/>
      </FIELDSET>
    </FIELDSET>
    <FIELDSET min="2" max="2" label="Contact Date and Time" entered="yes">
      <FIELD id="10" type="date" name="whenDate" size="8" initial="today" label="Date" value="4/8/00" entered="yes"/>
      <FIELD id="11" type="time" name="after" size="5" initial="now" label="After" value="14:16" entered="yes"/>
    </FIELDSET>
  </FIELDSET>
  <!-- area of interest -->
  <FIELD id="12" type="select" name="areaOfInterest" label="Area Of Interest" entered="yes" value="Internet Access Plans">
    <OPTION selected="yes" value="Internet Access Plans">Internet Access Plans</OPTION>
    <OPTION value="Web Hosting" selected="no">Web Hosting</OPTION>
    <OPTION value="Intranet Solutions" selected="no">Intranet Solutions</OPTION>
    <OPTION value="Internet Solutions" selected="no">Internet Solutions</OPTION>
    <OPTION value="Electronic Publishing" selected="no">Electronic Publishing</OPTION>
    <OPTION value="IT Support" selected="no">IT Support</OPTION>
  </FIELD>
  <!-- comments -->
  <FIELD id="13" type="textarea" name="comments" label="Comments"/>
  <FORM-ERRORS>
    <ERROR message="Field is required" name="First Name"/>
    <ERROR message="Field is required" name="Last Name"/>
    <ERROR message="Field is required" name="Email Address"/>
    <ERROR message="Details required" name="Select preferred number"/>
  </FORM-ERRORS>
</FORM>

You can see from the above XML how the error messages have been added, the FIELD and FIELDSET elements in error have been tagged and the formStatus has been set to error. You can also see how the LOOKUP element has been replaced with OPTION elements and the initial fields have had their values set.

If the validation is successful, the temporary XML form document is deleted.

Converting to HTML

The conversion to HTML is done in the simple function displayForm , which takes a stylesheet name and the passed XML form object and uses the transformNode method to generate the output.

Running the example

To run the example, download and unzip the file. You will need to change the value of the strPath variable in test.asp and create a DSN called testing for the Access database.

A stylesheet called error.xsl has also been included. If the XML document does not load properly an error document is created which is formatted using this stylesheet. This helps with any problems you have with a form XML document.

Using the form handler in your own applications

It is easy to include the handler in your own applications. Just follow these steps:

  1. Create an XML form document
  2. Create a form stylesheet
  3. Include the following code in your ASP:
strPath      = ( physical path of application goes here (
strFormName  = ( form name (without .xml) goes here (
strFormStyle = ( form stylesheet name (without .xsl) goes here (
strFormError = "error"
	
If processForm(strFormName,Request) = "validated" Then 
     ( post form processing goes here (
   Next
End If

Don’t forget to change the strPath to the appropriate path!

  1. Include the processForm.asp file in your ASP

Summary

The form handler in this article only scratches the surface of what is possible. It is a relatively simple task to add additional types , initialization parameters and the option of initializing multiple FIELDS from a database record; to expand the validation to perform "look–ups" on database tables; and to add some common post–validation processing such as saving the details to a text file, database table or emailing the results.

Simple as it may be though, it has hopefully shown you the huge benefits of using an XML approach to form processing. It really does make forms truly portable and whilst it won’t make form handling a pleasant task, it should make it slightly more bearable!

 
 
   
  RATE THIS ARTICLE
  Please rate this article (1-5). Was this article...
 
 
Useful? No Yes, Very
 
Innovative? No Yes, Very
 
Informative? No Yes, Very
 
Brief Reader Comments?
Your Name:
(Optional)
 
  USEFUL LINKS
  Related Tasks:
 
 
   
  Related ASPToday Articles
   
  • International Webforms using XML (August 20, 2001)
  • Site News Application Using ASP and Server-side XML (August 18, 2000)
  • Code Layer Separation in IIS Webclass Applications using XML and XSL (July 27, 2000)
  •  
           
     
     
      Related Sources
     
  • MSDN XML site: http://msdn.microsoft.com/xml
  • XForms, 'the next generation of web forms': http://www.w3c.org/MarkUp/Forms
  • XML.com: http://www.xml.com/
  •  
     
           
      Search the ASPToday Living Book   ASPToday Living Book
     
      Index Full Text Advanced 
     
     
           
      Index Entries in this Article
     
  • advantages
  •  
  • ASP shell
  •  
  • converting XML to HTML
  •  
  • disadvantages
  •  
  • dynamic form manipulation during processing
  •  
  • example
  •  
  • extremely basic form definition
  •  
  • form handler, example
  •  
  • form validation
  •  
  • form, XML document
  •  
  • HTML
  •  
  • HTML and XML-based forms, comparing
  •  
  • HTML and XML-based web forms, comparing
  •  
  • infinite tags - infinite possibilities
  •  
  • inflexibility
  •  
  • loading the form
  •  
  • merging of function and style
  •  
  • near-impossibility of reusing
  •  
  • overview
  •  
  • pre-validation processing
  •  
  • presetting form field values, lacking
  •  
  • Request.Form collection
  •  
  • running the example
  •  
  • separation of formatting, content and functionality
  •  
  • storing definition using XML document
  •  
  • storing web form definition, using
  •  
  • superior validation capabilities
  •  
  • using in applications
  •  
  • validator, field name extensions
  •  
  • validator, hidden fields-based
  •  
  • web form handler, XML-based
  •  
  • web forms, HTML-based
  •  
  • web forms, XML-based
  •  
  • XML
  •  
  • XML and HTML-based web forms, comparing
  •  
  • XSL stylesheets
  •  
     
     
    HOME | SITE MAP | INDEX | SEARCH | REFERENCE | FEEDBACK | ADVERTISE | SUBSCRIBE
    .NET Framework Components Data Access DNA 2000 E-commerce Performance
    Security Admin Site Design Scripting XML/Data Transfer Other Technologies

     
    ASPToday is brought to you by Wrox Press (http://www.wrox.com/). Please see our terms and conditions and privacy policy.
    ASPToday is optimised for Microsoft Internet Explorer 5 browsers.
    Please report any website problems to webmaster@asptoday.com. Copyright © 2001 Wrox Press. All Rights Reserved.