asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Dynamically Generated and Validated Forms
By Gaddo F. Benedetti
Rating: 2.7 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction

    Sometimes developers forget that not everyone can code in HTML. Fewer still can code in JavaScript; server-side scripting in ASP, Perl, and Cold Fusion is rarer still. However, there are occasions where one may want to be able to hand over a project to a nondeveloper and know that they have the option to update it themselves.

    With regard to most content, this is easy. Database-driven Web sites and Intranets have been around for quite a while, with page text, tables, and even Java scrollers being updated on a regular basis by others, while you continue on with something more interesting. However, when faced with complex forms that must be updated on a regular basis, including validation (server and/or client side), things can start going pear shaped.

    Examples

    An example of this might be a site that sets a questionnaire every week to the public. This is simple enough to update if the form is basic in structure, but what happens if the number of fields or rules of validation vary?

    In this example, we can use a database to define and store information about our form. We can even use the same database that will eventually hold the information that is submitted to the form. However, returning to our form definition, we will need two tables; one for the form field definition and a second to hold subelements to each field, such as list options.

    Our definitions table should hold the following information:

    • FieldName – the variable name we are assigning to the form field
    • Label – the display label that will be attached to the field for the user’s benefit
    • Type – a one-character code defining what type of form element will be displayed and what type of data is expected. In our example here, I’ve limited it to the following:
      • (t) A simple text box, i.e. <INPUT TYPE=”TEXT”>
      • (n) A simple text box, as above, but designed to take in numeric values
      • (m) A “memo” field in a text area, for comments or other entries where a simple text box would not suffice
      • (b) A Boolean field. In this case, I represent this as a check box with the word “Yes” next to it. Checked, it returns an “on” value; unchecked, it returns nothing.
      • (r) A series of radio buttons
      • (l) A drop-down list
    • Min – This is only used in the case of numeric fields, and it is the minimum numeric value. In the example, where I’ve defined “Age” as a numeric field, this is set as 1.
    • Max – The nature of this is dependent on the field type. In the case of a numeric value, it is the maximum numeric value allowed. For example, in the case of our “Age” field, this is 100. For simple text boxes, it is the maximum length of the text entry, in characters, and for memo fields, it’s the number of visible rows is the text area.
    • Required – A Boolean value that defines whether the field is mandatory or not. If not filled out, such fields would be trapped by the validation process and would also be marked by an asterisk on the form, which would point to a footnote that advises the user to their mandatory nature.

      For the example form I’ve used, which is a simple ASP developer’s survey, I’ve defined the following fields:
      FieldName LabelTypeMinMaxRequired
      NameNameText (t)n/a50No
      AgeAgeNumeric (n)1100No
      SexSexRadio (r)n/an/aYes
      E-mailE-mail AddressText (t)n/a50Yes
      LanguageWhat language do use to code yourDrop-down List n/an/aNo

      Our second table, “Lists,” is home to the subelements that populate the options given to the user in the “Sex” and ”Languages” fields. The table is simple enough, containing only three fields:

      • FieldName – The form element to which this item belongs
      • Value – The value of the option
      • Label – The text label that the user sees

      For “Sex,” we only have two items ? “Male” and “Female.” For “Language,” the list is a little longer, allowing for a number of the languages that are used with ASP, such as VBScript, JavaScript, C, Perl, and the infamous “other.”

      Our third table, “Records,” where the user submissions will eventually be recorded, also holds three fields:

      • Record – A memo field that will store the entire submission in a querystring format
      • Created – The date/time of the submission
      • RemoteIP – The remote address of the user who made the submission
      One could grab additional information from the user, but for this simple example, I’ve limited this extra information to creation date and IP address.

      Now that our database is constructed and our form defined, we can turn our attention to the script that will create our form, validate it, and finally handle it, recording users’ submissions.

      Whether we are constructing the form or handling it, there are three things that we will always be doing. The first is defining the type of validation, which we pass as a querystring when constructing the form or as a posted hidden field when handling it. This allows us to use the form more efficiently, perhaps by validating it server side only if JavaScript is disabled. Nonetheless we have four options: no validation, client-side JavaScript, server-side ASP, and both (which will be our default - if no or an invalid querystring is sent).

      
      iValType = Request.QueryString("val")
      	If IsNumeric(iValType) = False Then iValType = 3
      	If iValType > 3 Or iValType < 0 Then iValType = 3
      
      
      We also want to create our Open DataBase Connectivity (ODBC) connection and two recordset objects: RS, which will be our main recordset object (initially from the Definitions table), and RSList that we'll use when cross-referencing related tables later. (Note that in the example script I've included the code for either a Data Source Name [DSN] or DSN-less ODBC connection.)

      Finally we want to create the HTML headers and footers to the page body at the top and bottom of the script and destroy our ODBC objects before terminating the script. Once all this is done we can get to the middle, more intelligent part of the application.

      The script itself represents two pages ? the form and a “form-submitted” end page, which also records the submission to the database. The simplest means of deciding which is called is by checking whether FORM data has been POSTed. If so, we handle the form; if not, we construct it.

      We construct both the HTML for the form and the JavaScript to handle it one piece at a time, record by record, element by element. With the HTML, we begin by creating a label for the element:

      
      sHTML = sHTML & vbTab & "<TR>" & vbCrLf & vbTab & vbTab
      sHTML = sHTML & "<TD VALIGN=" & Chr(34) & "TOP" & Chr(34)
      sHTML = sHTML & ">" & vbCrLf &  vbTab & vbTab & vbTab
      sHTML = sHTML & "<B>" & RS.Fields("Label")
      
      
      Next, we check if the field in question is required. If so we add an asterisk to the label which will point to a footnote that informs the user that the field is required. If the field is required, we also have to create the JavaScript code to validate it. In the case of either radio buttons or a drop-down list, we have to send it to further, fixed, functions that would check to see that something is selected. With all other types we only have to check that the value is not null.

      We close the label cell and write the element to the page, based on the type and attributes given to it in the Definitions table. Now the JavaScript has to be appended, depending upon the type of field type. With regard to this example only numeric fields need to be further checked to see that they contain numeric values, and that these are within the allowed maximum and minimum values. Finally, we close our table row and carry on through our recordset, at the end of which we add the forms submit and reset buttons. In essence what we're doing is treating each field as a new table row that is two cells long, the first displaying the field label and the second containing the field element itself.

      Both the code for the form’s HTML and JavaScript are accumulated by this process into two variables: sHTML and sJavaScript. Just as we are about to begin writing them to the page, we check if JavaScript validation is required, and clear sJavaScript if it's not:

      
      If iValType = 0 Or iValType = 2 Then sJavaScript = ""
      
      
      After the body tag, we begin writing our JavaScript functions:
      
      <SCRIPT LANGUAGE="JavaScript">
      <!--
      	function validate(TheForm)
      		{
      <%=sJavaScript%>
      		return true;
      		}
      	
      	function CheckRadio(objRadio)
      		{
      		for(var n = 0; n < objRadio.length; n++)
      			{
      			if(objRadio[n].checked)
      				{
      				return true;
      				}
      			}
      		return false;
      		}
      	
      	function CheckList(objList)
      		{
      		for(var n = 1; n < objList.length; n++)
      			{
      			if(objList.options[n].selected)
      				{
      				return true;
      				}
      			}
      		return false;
      		}
      //-->
      </Script>
      
      
      The “validate” function is left to return a simple ”return true” if we don't require JavaScript validation. The latter two static functions, CheckRadio, and CheckList, are called from ”validate” when checking that a radio or drop-down list field has a valid selection.

      Now we write our form to the page, beginning with:

      
      <FORM ACTION="./dform.asp" METHOD="POST" NAME="MyForm" onSubmit="return validate(this)">
      
      
      which submits to our script only if the “validate” function returns “True.” Thus if JavaScript validation is switched off and the client is nonetheless JavaScript-enabled the validate function will automatically return ”True.”

      Next, we add the hidden field for the validation type:

      
      <INPUT TYPE="HIDDEN" NAME="val" VALUE="<%=iValType%>">
      
      
      so that upon processing, the script knows whether server-side validation is required.

      We begin by adding a title label to our form ? sTitleLabel ? which we defined as a constant at the top of our script.

      
      <TABLE BORDER="0">
      	<TR>
      		<TD COLSPAN="2" ALIGN="CENTER">
      			<H2><%=sTitleLabel%></H2>
      		</TD>
      	</TR>
      
      
      Note that an extra field in the Definitions, Lists, and Records tables called FormID could be used to separate different forms that are stored in the same database. This allows the Webmaster to run numerous forms from the same script. A table, Forms, could also be used to store global form data, such as sTitleLabel.

      We now add our HTML form code and submit/reset buttons, and finally we check to see if an asterisk is present in sHTML, denoting the presence of a mandatory field, and prompting the script to add a footnote to our form informing the user of their existence:

      
      <%=sHTML%>
      	<TR>
      		<TD COLSPAN="2" ALIGN="CENTER">
      			<INPUT TYPE="SUBMIT" VALUE="Submit"> 
      <INPUT TYPE="RESET" VALUE="Reset">
      		</TD>
      <%
      		If InStr(sHTML,"*") Then
      %>
      	</TR>
      		<TD COLSPAN="2" ALIGN="CENTER">
      			<FONT SIZE="2">
      <B>Please Note: </B> The fields marked with an asterisk (*) are mandatory.</FONT>
      		</TD>
      	</TR>
      <%
      		End If
      %>
      </TABLE>
      
      </FORM>
      
      
      Our form and the first half of our script is now complete.

      The latter half our form is the server-side handling - validation, recording the data to the database, and any submission accepted/submission error messages that are needed. We check the validation of our form using the string sBadForm, to which we write our error message. If it's empty by the end of our validation processes, then the submission is valid; otherwise we reject the submission and write sBadForm to the page.

      Regardless of the validation type (passed is the hidden form field “val,” above) it is good practice to check the POSTs referrer. Such a practice prevents your script from being hijacked, particularly important if your script involves E-mailing form results. Checking that the POST has come from a page or script on your own site is simply done by comparing the necessary server variables thus:

      
      If InStr(Request.ServerVariables("HTTP_REFERER"), _
      Request.ServerVariables("HTTP_HOST")) = 0 Then
      	sBadForm = "<LI>Form was submitted from an invalid location" & vbCrlf
      End If
      
      
      Checking that server-side validation is requested, we run through our form definition recordset in much the same way as when we constructed our form. (The form definition recordset is opened at the top of our script, since it's used in both constructing and validating our form.) This time, however, we're simply validating our form and adding to our sBadForm string as we find invalid data.

      Finally, we check that sBadForm is empty. If not, we reject the form submission, writing sBadForm to the page.I If so, we add a new record to our Records table and add the submitted data (parsing out the unnecessary “val” field, which is always passed as the first element):

      
      If Len(sBadForm) = 0 Then
      	RS.Open "Records", DB, 3, 2, &H0002
      	RS.AddNew
      	RS.Fields("Record") = Mid(Request.Form, InStr(Request.Form, "&") + 1)
      	RS.Fields("Created") = Now()
      	RS.Fields("RemoteIP") = Request.ServerVariables("REMOTE_ADDR")
      	RS.Update
      	Response.Write("<H1>Thank you for your Submission</H1>")
      	RS.Close
      Else
      	Response.Write("<H1>Your Submission was not processed</H1>")
      	Response.Write(vbCrLf & sBadForm)
      End If
      
      
      And with that our script is finished, assuming we've encapsulated the two halves of this script correctly in the main “If-Then-Else-End If” conditional, based on the existence of POSTed data, we've already written our HTML headers/footers, and destroyed our ODBC objects.

      This script is only an example, so I've omitted many features. Allowing multiple forms, governed by a global definitions table, would be one such feature. Such a table could also tell the form if it should record the data or E-mail it, using the Collaboration Data Objects for Windows NT Server (CDONTS) objects library.

      Another glaring omission is an update center that would allow a nondeveloper to add, delete, and amend the form or access the collected data. This is another application in itself and a more orthodox one that an ASP developer would be far more familiar with.

      Field types are also limited in this example. Image or hidden fields are not catered for, and customized field types, such as text fields that are specifically designed to take in and validate E-mail addresses or credit card numbers, are not included, but could be added.

      However, when faced with a site that requires a new validated form to be designed on a regular and frequent basis, this will take the long-term drudgery out of the work and give the client, whom we assume is nontechnical, direct control over the site.

      Download

      You can download the complete source for the sample contained in this article:
      http://15seconds.com/files/000224.zip

      About the Author

      Gaddo F. Benedetti is an Internet and software developer in Dublin, Ireland. He specializes in server-side applications and tools for the Wireless Application Protocol (WAP), Web spiders, and Case Base Reasoning (CBR) search agents. He has a fondness for both Guinness and pasta, but not at the same time.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Aug 7, 2002 - Using MySQL in the Win32 Environment
    Developers who don't want to spend a lot of money on SQL Server and who want a database that's more robust than Access may find MySQL to be a pleasant alternative. This introductory article covers the bare essentials for getting MySQL installed and running in the Win32 environment.
    [Read This Article]  [Top]
    Jul 17, 2002 - Software Development: Steps To Better Ensure Success
    There is never a guarantee of project success when endeavoring to build a sophisticated application. However, there are established steps to follow that will ensure a clear, concise scope, support for the team involved, and a solid opportunity for successful deployment.
    [Read This Article]  [Top]
    Jul 15, 2002 - Securing SQL Server for Web Applications
    If your SQL Server is exposed to the Internet, then hackers are probing it. This article shows how to secure a SQL Server database that's being used with a Web application
    [Read This Article]  [Top]
    Jul 1, 2002 - Protecting Your Web Application Against Dangerous Requests
    Enrico Di Cesare provides a solution for hiding and securing querystring values that pass through a url.
    [Read This Article]  [Top]
    Apr 2, 2002 - Object-Oriented Programming for VBScripters
    Feel intimidated by .NET? This article by Rob Chartier is designed to ease any level VBScripter (ASP) into .NET by clarifying some OOP concepts.
    [Read This Article]  [Top]
    Mar 27, 2002 - A Best Practice for Using ADO Objects
    A few members of the 15 Seconds discussion list talk about the proper way to use methods in order to prevent ADO object errors.
    [Read This Article]  [Top]
    Jan 2, 2002 - The ASP.NET Page Life Cycle
    Solomon Shaffer explores the life cycle of an ASP.NET page from initialization to unloading. He also explains the various methods to override ASP.NET server-side events.
    [Read This Article]  [Top]
    Dec 19, 2001 - Application Architecture: An N-Tier Approach - Part 2
    Rob Chartier creates a simple portable and reusable address book in .NET to demonstrate the power of N-tier application architecture. Complete source code included!
    [Read This Article]  [Top]
    Oct 23, 2001 - Application Architecture: An N-Tier Approach - Part 1
    Learn about N-tier application architecture and realize that developing with multiple layers produces a flexible and reusable application for distribution to any number of client interfaces.
    [Read This Article]  [Top]
    Oct 23, 2001 - Application Architecture: An N-Tier Approach - Part 1
    Learn about N-tier application architecture and realize that developing with multiple layers produces a flexible and reusable application for distribution to any number of client interfaces.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers