Topics
Home • ASP Form Handling • HTML Coded Character Set • Resources for Setting up an Online Store • Setting up Email Accounts • Font Sizes to use in your HTML • Creating a FrontPage Drop-Down Menu with JavaScript • Setting up an FTP server with Windows 2000   Jun 25 • Hex Color Chart • HTML Cheatsheet • HTML Safe Color Palette • IIS HELP • Links • Free META Tag Builder • Working with PowerPoint Presentations from Access Using Automation • Photoshop Tutorials • A TCP/IP Tutorial • Web Site 101 • Configuring Dial-up Networking for Windows 98

Using ASP for Form Handling

Note from Will:
I don't do ASP, I just compiled this Article from a bunch of different web pages.

In this article, we will discuss how to use Microsoft ASP technology to handle user-submitted form data and then send that data to someone via email with Microsoft's Collaboration Data Object for NT Server (CDONTS).

Introduction

Microsoft's Active Server Page technology is a powerful server-side scripting method of web development that allows any web developer with a web server powered by NT's Internet Information Services (IIS) and a basic understanding of HTML and VBScript to create powerful dynamic web pages.

This article assumes that you have the basic HTML and VBScript understanding mentioned above. However, I will explain anything that is crucial to your understanding.

If you have ever created or thought about creating an HTML form for user input on your web site, then you must have also dealt with the issue of handling the data once it is submitted (ie. where does the data go and how does it get there). As you may already know, if you want the information submitted to be emailed to you, you can simply put your email address in the action field of the FORM tag like this:

<form action="mailto:corinth@enfused.com" method="get" enctype="text/plain">

TIP: If you do not have time or the resources to program an ASP page or Perl script to handle your form's submitted data, you can use a little-known HTML trick to make the submitted form data reach your inbox in a legible fashion. By adding enctype="text/plain" to your form tag, the output will come across as standard plain text rather than that garbled mess that normally comes across when you set the action equal to mailto:some_email@address.com.

However, you probably also know that when you use the mailto action, your users will get an obnoxious and frightening security warning, and we do not want to scare your users away!

To avoid the security alert, you have a couple of options. First, if you are developing in a UNIX environment, using Perl and CGI would probably be your best bet. If that is the case, you should check out Aaron Weiss' The Perl You Need to Know series of articles here at the WDVL.

On the other hand, if you are developing in an NT environment, while you may still use Perl and CGI if Perl is installed on your server, it is recommended that you use ASP because it is easier to code and a bit more intuitive, for novices and experts alike.

In the remainder of this article, I will show you how to use ASP to handle the form data and then send it to an email address using the Collaborative Data Object for NTS (CDONTS), a special Windows NT COM object designed to send mail through the SMTP service on your web server.

Contents:

Creating the Form
Adding the ASP Code
Making the ASP Page Smart
Working with CDONTS
Putting It All Together and Wrapping Up


Creating the Form

For simplicity's sake, and to keep all this new information from getting garbled in your brain, we are going to create and use a very simple form that collects only a user's first and last name. If you do not know how to make an HTML form, you can read Alan Richmond's introduction to forms at the WDVL or you can visit Webmonkey for another easy forms tutorial.

Our form page is very simple, so here is the code (we will leave action blank until later):

<html>
	<head>
		<title>ASP Form Sample</title>
	</head>
	<body>
		<form action="" method="get" name="Input_Form">
			First Name:
			<input type="text" size="30" maxlength="50" name="First_Name">
			<br>
			Last Name:
			<input type="text" size="30" maxlength="50" name="Last_Name">
			<br>
			<input type="submit" value="Submit Form">
		</form>
	</body>
</html>

This is what our little bit of code produces:

First Name:
Last Name:

TIP: To make your form fields look nice and aligned on screen, put them in a simple table with two columns to provide more precise positioning.

If you are following along, save your file as formtest.asp. Or, name it whatever you want but make certain that the file has the .asp file extension. If you have access to an NT server, upload the file and test it to make sure your form is coded correctly. If you do not have access to an NT server, you may download Microsoft's Personal Web Server and test the ASP page on your local machine (Note: When we work with CDONTS later, that will not work on Personal Web Server, it is supported by only NT Server).

Now on to something a little more difficult (and fun)! How in the world can we make this form go to my email address at corinth@enfused.com without popping up that ugly security alert box? It is really easier than you think. Move on to the next page and I will show you how.


Adding the ASP Code

Now we have got a nice clean HTML form just crying to be used, but it does not have any action - nowhere to go with submitted data. Next we will add some ASP to make the page more useful.

First, we will begin by adding an action to our form. For this particular form, we are just going to make it the name of our file. However, in many situations you can make it the name of another page depending on what you are doing with the form. Since I named the file formtest.asp, then my action tag will look like the following:

<form action="formtest.asp" method="get" name="Input_Form">

Well, that was pretty easy, but where does the ASP come in? So far this page is like just any old page that you could have done in your sleep. All right then, ask and you shall receive! We are now going to add some ASP code to capture the submitted form data and store them in variables.

To begin with, we need to add a fun little symbol to our page that tells the web server ASP code is coming ahead. For our form, we should put this symbol before any HTML code in our sample page. Take a look:

<%
' Note: A single quote denotes a comment in ASP
' (which is primarily powered by VB), just like // double
' forward slashes denote a comment in JavaScript or C++.
' You guessed it, that little <% starts the ASP part of
' the page and if you are really sharp you will also
' guess that %> ends the ASP part of the page.

%>
<html>
	<head>
		<title>ASP Form Sample</title>
	</head>
	<body>
		Our form code, etc...
	</body>
</html>

All right, put your thinking caps on, this next part is crucial to making your page work properly. Up until now we have not talked about the infamous method attribute of the form tag. For an ASP page, this part of the form is particularly important in that it will dictate how you create the ASP form handling code. If you use the post method, then the server will "post" the submitted form data "behind the scenes." That means the user will not be able to see what happens to the data they entered, but a script properly coded will be able to access and manipulate that data.

On the other hand, if you use the get method, then the server will append the submitted form data at the end of the URL in your browser's address bar. You have seen this before (it looks like a bunch of &formfieldname=inputeddata&formfieldname2=inputeddata at the end of the URL - it is called the querystring); a lot of the search engines use it so that you can bookmark your search results page (something you cannot do when the post method is used).

So which method is best? There is not clear-cut answer to that question, suffice it to say that it depends entirely on your needs and what your form does. Basically, if you want to let the user bookmark the resulting page, use the get method. Otherwise, use the post method.

I am going to briefly show you how to code the ASP for both methods. ASP deals with two fundamental objects (there are more, but we are only dealing with the big two in this particular article): Request and Response. Response has many uses and methods (a method is a function that an object performs), but its primary use is to write text (or HTML) to a web page. Request also has many uses and methods, but it is primarily used for obtaining information from the client. Remember, we are dealing with a server-side scripting environment, so it all makes sense. The server "responds" to a client "request." Got it? If not, I will provide some links to some ASP resources at the end of this page.

With either method, you must use the Request object to get the submitted information. If you decided to use the post method, you will need to use the following code:

<%
	Dim fname, lname

	fname = Request.Form("First_Name")

	lname = Request.Form("Last_Name")
%>

In the above code, we are simply using the Forms collection (or a group of common or related items - namely the fields of the form) of the Request object to get the information that the user submitted on your web page. The syntax for objects and collections or methods is simple and consistent throughout ASP pages (with few exceptions): Object.Collection("ITEM_NAME") or for methods, Object.Method("METHOD_PARAMETERS").

If you chose the get method (which is assumed throughout the rest of this article), you cannot use the Forms collection at all and must use the Querystring collection, which acts exactly the same as the Forms collection except it is simply a collection of data in the querystring. Here is the code:

<%
	Dim fname, lname

	fname = Request.Querystring("First_Name")

	lname = Request.Querystring("Last_Name")
%>

Again, the above code uses the standard Object.Collection syntax as I described before. You will note that in both cases, the Item Name is the same as the name attribute of the form's input tags. That is not an accident. Whether you use the Querystring or Form collection, you will need to reference the name you assigned to the input tags when you created your form.

At this point, I would say we are doing pretty well, but there is one problem: every time someone accesses the page, this ASP code is going to be executed. What if we add some Response code to write a little thank you message, like this:

<%
	Dim fname, lname

	fname = Request.Querystring("First_Name")

	lname = Request.Querystring("Last_Name")

	Response.Write("Thanks for submitting your name!")
%>

Even if the user never submits the form, they are going to see the thank you message and that is no good! What is worse, once we add CDONTS, the server will return a cryptic ASP error - and you want to avoid them, trust me.

On the next page, we will discuss how to avoid this annoying problem using a hidden form field and some simple conditional testing.

ASP and VBScript Links:
15 Seconds (Advanced)
ASP Toolbox
ASP Watch
Learn ASP
MS on ASP Microsoft VBSCript Reference PowerASP
Webmonkey ASP Tutorials


Making the ASP Page Smart

Christopher Assenza

July 31, 2000

We have got a web page, a simple form and some ASP code to store any submitted data in variables, but sadly, our page is a page of very little brain. Everytime the page is called from the browser it executes the ASP whether the user presses submit or not; and, while it will not cause problems as-is, as soon as we add code that actually does something with those variables, things will get messy. Just look at how ugly ASP error messages are:

Microsoft VBScript compilation error '800a03f9'

All right, all right, you caught me, I am exaggerating a bit. The error messages are not that bad, they usually include a line number and some frighteningly intelligent help message. *grin*

Moving on, I think the reader will agree that we should avoid those crazy errors altogether. In order to ensure that our web page does not execute the form handling code without submitting the form we can use a very simple conditional test using if...then logic. We will test for a special "hidden" form field that we add to our form like so:

<form action="formtest.asp" method="get" name="Input_Form">

	<!--Existing form code-->
	First Name:
	<input type="text" size="30"
	maxlength="50" name="First_Name">
	<br>
	Last Name:
	<input type="text" size="30"
	maxlength="50" name="Last_Name">
	<br>
	<!--Insert new form field-->
	<input type="hidden" name="isSubmitted" value="yes">
	<!--Finish off form with the rest of the exisiting code-->
	<input type="submit" value="Submit Form">

</form>

If you are not familiar with hidden form fields, do not worry, they are really self-explanatory. Basically they are form fields hidden from the user's view in that they do not show up on the web page but are submitted with every other field and are given the value you, as the designer, assign when the page is created. Easy, no?

For our purposes, the hidden form field is named descriptively as "isSubmitted" with an assigned value of "yes." Here we come to the hardest part of making our ASP smart - the ASP! However, you will quickly see that it is considerably less difficult then you may be expecting.

To begin, we need to revisit our existing ASP code:

<%

	Dim fname, lname

	fname = Request.Querystring("First_Name")

	lname = Request.Querystring("Last_Name")

	Response.Write("Thanks for submitting your name!")
%>>
Now, to add some conditional testing all we need to do is take this existing code and put it inside a simple if...then statement like so:
<%
	if [some condition is true] then

		Dim fname, lname

		fname = Request.Querystring("First_Name")

		lname = Request.Querystring("Last_Name")

		Response.Write("Thanks for submitting your name!")
	end if
%>

All that is missing is the condition itself (indicated above as [some condition is true] above), which is equally easy thanks to the QueryString Collection that we discussed before. Let's walk through this one together so there are no questions in anyone's mind about how the condition is set up. First, what variable are we testing for? Every conditional test has to have a variable to test and an anticipated result that is either determined to be true or false in each case. How about Request.Querystring("isSubmitted") = "yes"?

TIP: If you are relatively new to VBScript (the language driving the ASP), then you should note that it is syntactically different from JavaScript. For instance, if you were coding an if...then statement in JavaScript then you would type:
if (condition is true) { processing... processing... } In VBScript, you have to remember to include then and end if
as illustrated above. If you leave these things out your code will not work properly.

In this case our test variable is the isSubmitted form field as it is stored in the querystring after submission. The anticipated result is that this condition will be true and then execute whatever code follows the then part of the if statement. If the condition is false (if Request.Querystring("isSubmitted") does not equal "yes" or is empty (which occurs only when the form is not submitted), then the ASP form handling code will not be executed.

At this point, you should be starting to see the potential of ASP form handling. For example, you can check the validity of form fields with server-side ASP instead of using client-side JavaScript. If the user has a browser that does not support JavaScript or they have it turned off, your ASP web page will still be smart enough to validate their submitted data.

Another possible use for the skills obtained through this tutorial would be to create individual portions of a web page dynamically, as the user is actually using the page. For instance, when I was working on Carcruises.com, the owner asked if we could have a more intuitive way of finding car cruises. So, we developed a system wherein the user picks the state for which they want to locate a cruise. Then, the ASP form handling code matches the selected state to the corresponding months available in the database using an SQL query. Next, the ASP writes a new select box to the page that lists the results of the query. Not only is this method more functional, it leaves room to make web pages that are incredibly intelligent. To top it off, it was all done using the techniques we have been discussing (and a little SQL of course).


Working with CDONTS

Christopher Assenza

July 31, 2000

All that remains to be done at this point is to process the submitted form data; and, as I told you in the beginning, we are going to send the data via email to your email account using Windows NT Server's Collaboration Data Object (CDONTS).

However, to use CDONTS, we ought to know what it is first. The Collaboration Data Object, according to some Microsoft documentation:

"CDONTS is a Simple Mail Transfer Protocol (SMTP) specific OLE server that is specifically designed to provide Messaging functionality to Web-based applications."

In non-Microsoftese, that means CDONTS is something that acts as the middleman between your web page and the SMTP server, enabling communication that will allow you to send data from the web (like our form) to someone via email.

CDONTS is very powerful and feature-rich, but for now, we are going to keep it simple. I will provide links for some other tutorials on CDONTS at the end of this page. First things first, whenever you use a server object like CDONTS you need to invoke an instance of it (or, in simpler terms, make it available for use). To do that we are going to add a few lines to our form handling code. All the code for CDONTS is explained line-by-line following the example.

<%
	if Request.Querystring("isSubmitted") = "yes" then

		Dim fname, lname
		Dim objCDO
		fname = Request.Querystring("First_Name")
		lname = Request.Querystring("Last_Name")

		'Here is where we insert new code to invoke CDONTS

		'This line invokes the object using the name objCDO
		Set objCDO = Server.CreateObject("CDONTS.NewMail")
		objCDO.From = "corinth@enfused.com" 'That's me :)
		objCDO.To = "youremail@domain.com"
		objCDO.Cc = "someoneimportant@whitehouse.gov, buycheese@cheese.com"
		objCDO.Bcc = "bgates@microsoft.NET"
		objCDO.Subject = "Submitted form data from my page"
		objCDO.Body = "Name: " & fname & " " & lname
		objCDO.BodyFormat = 1
		objCDO.MailFormat = 1
		objCDO.Send
		'Notice that response.write changed to ConfirmMsg =
		'I will explain why in just a little while.
		ConfirmMsg = "Thanks for submitting your name!"
	end if
%>

Now, let's go through that line-by-line, so you know exactly what is going on. Keep in mind that everytime you want to reference a method or property of the object you invoked, you need to use the name you assigned (in this example, objCDO followed by a period, as illustrated below. (Note: It does not matter in what order these values are assigned, so long as they all precede the Send command).

To begin, From is the email address, as a string, of the user sending the email. For now, make this your email address. Normally it would be wise to allow the user to fill this field in, and I will show you how to do that at the end of the article. However, I recommend that you try it on your own first to ensure you have a grasp on what we have been doing thus far.

objCDO.From = "corinth@enfused.com" 'That's me :)
TIP: Do not send me spam On the other hand, all legitimate emails, questions, comments or criticisms are welcome. Just keep in mind that I am a busy guy and may not be able to reply very promptly to all of them.

To is the email address of the intended recipient. Make this field your email address(es). Multiple Addresses may be separated by commas (in any field as a matter of fact). Do not forget the quotes in any of these fields, they must all be string values.

objCDO.To = "youremail@domain.com"
CC, BCC are the email addresses of any Carbon Copies or Blind Carbon Copies you would like to send.
objCDO.Cc = "someoneimportant@whitehouse.gov, buycheese@cheese.com"

objCDO.Bcc = "bgates@microsoft.NET"

Subject is any string you provide that will be displayed as the subject of the email,

objCDO.Subject = "Submitted form data from my page"
Body is the body, or main content, of the message. You can put anything you want in here, in the format of a string, so long as it can be sent via email. We are just going to put our variables in here and send them.
objCDO.Body = "Name: " & fname & " " & lname
TIP: The above code illustrates an important and powerful element of ASP and CDONTS, the designer can assign variables to these CDONTS attributes rather then using hard-coded strings. That ability expands your capacity to work creatively. Try to come up with some ways to make your life easier by using string variables. Perhaps you could make the subject a form field, thereby allowing users to submit their own subject.

The next two properties determine the type of email sent, whether it is HTML or plain text. For our purposes, we will be sending the message as plain text. However, should you want to send HTML simply change these values to 0 and make the Body string HTML code.

objCDO.BodyFormat = 1

objCDO.MailFormat = 1

Finally, the last bit of code actually tells the server to send the message.

objCDO.Send

As for that little trick with ConfirmMsg = instead of Response.Write, that was done in order to better format our confirmation message. When we apply the final touches to the whole page, I will show you what we are going to do with the ConfirmMsg variable.

That is really all there is to CDONTS, at least for our purposes. I have created a handy CDONTS reference table to help you while you are coding. All that remains is for you to move onto the next page where we will put it all together and I will show you a few extras you can add in, should you so desire.

CDONTS Links:
ASP Today: Setting Up and Using CDONTS
15 Seconds: Sending HTML with CDO
15 Seconds: Collaboration Data Object and IIS 4.0
Power ASP: Using the CDONTS component...(includes attachments).
ASP Watch: Sending E-mail using CDONTS
Microsoft CDONTS Documentation


Putting It All Together and Wrapping Up

Christopher Assenza

July 31, 2000

We have come a long way since the beginning of this tutorial. If you have successfully made it this far then pat yourself on the back because you have learned a lot. Once you get some practice, you will be able to take this fairly simple concept, some creativity and some elbow-grease to create very intuitive and complex dynamic pages.

Below you will find the complete source code (for a working "live" version of the code, visit this test page I set up at Enfused). Following the code is explanation that should tie up any loose ends and some enhancements you may want to consider. As an additional note, I've removed the email addresses for the CC and BCC code in the example because we do not want to accidentally spam someone in case those dummy addresses I cooked up were real.

<%
	if Request.Querystring("isSubmitted") = "yes" then
		Dim fname, lname
		Dim objCDO
		fname = Request.Querystring("First_Name")
		lname = Request.Querystring("Last_Name")
		Set objCDO = Server.CreateObject("CDONTS.NewMail")
		objCDO.From = "corinth@enfused.com"
		objCDO.To = "corinth@enfused.com"
		objCDO.Cc = ""
		objCDO.Bcc = ""
		objCDO.Subject = "Submitted form data from my page"
		objCDO.Body = "Name: " & fname & " " & lname
		objCDO.BodyFormat = 1
		objCDO.MailFormat = 1
		objCDO.Send
		ConfirmMsg = "Thanks for submitting your name!"
	end if
%>

<html>
	<head>
		<title>ASP Form Sample</title>
	</head>
	<body>
		<% if ConfirmMsg <> "" then %>
			<h2><%= ConfirmMsg %></h2>
		<% end if %>
		<form action="formtest.asp" method="get" name="Input_Form">
			First Name:
			<input type="text" size="30"
			maxlength="50" name="First_Name">
			<br>
			Last Name:
			<input type="text" size="30"
			maxlength="50" name="Last_Name">
			<br>
			<input type="hidden" name="isSubmitted" value="yes">
			<input type="submit" value="Submit Form">
		</form>
	</body>
</html>

The first major change you are likely to notice is the extra code dealing with ConfirmMsg in the HTML portion of the page. As promised, I will explain.

<% if ConfirmMsg <> "" then %>

	<h2><%= ConfirmMsg %></h2>

<% end if %>

Using another conditional test, the page checks to see if ConfirmMsg is not a zero-length string (or is not empty). If ConfirmMsg is empty that means the ASP form handling code did not execute and assign "Thanks for submitting your name!" to ConfirmMsg and will therefore not write anything to the page. However, if ConfirmMsg is not empty, that means the ASP code was executed and it should display the message.

Another item of note is that one may use one line of ASP to initiate a conditional test or loop, followed by HTML and then followed with ASP again. The ability to "sandwich" HTML in between looping or condition testing becomes more important as the complexity of the HTML to be written on every loop or test increases. Also, note that the <%= ConfirmMsg %> is a special form of ASP code. When the <% is followed by an equals sign (=) then the ASP processor acts in an output mode, allowing the designer to use a variable name without typing response.write(varName).

The possibilities for enhancement here are endless. One possibility, that I asked you to try earlier, is to allow users to enter their own email addresses for the From attribute of CDONTS. To do it, first add a field to your form like:

Email Address: 
	<input type	= "text" 
		size	= "30" 
		maxlength	= "50" 
		name	= "Email_Address">

Then, using your ability to assign variables (and still assuming the get method is being used) add a variable for the email address, like so:

EmailVar = Request.QueryString("Email_Address")

Finally, change the CDONTS code to the following:

objCDO.From = EmailVar

You can do the same with any of the CDO variables, depending on your needs. At Enfused we designed a special "Recommend to a Friend" page that uses these same exact techniques, allowing the user to send mail from our site with whatever values they want.

Another possibility includes writing the submitted form data to a database, like we did on Enfused's Suggest a Site page. With only a little extra coding and some SQL know-how, doing this can be quite easy because ASP has a special database-connectivity object, called ADO, to make your life easier. For some more info about working with ADO, check out this recent WDVL article on the subject.

In this tutorial, we learned about Microsoft's Active Server Page technology and how to use it along with the NT's Collaboration Data Object (CDONTS), to create a page that will email user-submitted form data. Forms drive interactivity and the Internet, and correctly harnessed, will allow you to make the best web sites possible. With these techniques and some practice, the sky is the limit on what you can do.


Using ASP for Form Handling: Part 2 - Server Side Form-Field Validation

Chris Assenza

September 5, 2000

Ever need to make sure a user enters data in specific fields on a form, but did not know how? Ever need to make sure a phone number actually looks like a phone number? Most of us have and in this article, we will discuss how to use Microsoft ASP technology to validate data submitted from a form.

 

Introduction

In my last article, I introduced you to the idea of using Microsoft's Active Server Pages to handle data submitted from a form on a web page. With that foundation in hand and some practice, one can create powerful, dynamic web pages. Building on that foundation, this article will show you how to gather user input from a web-based form and then test the validity of that input.

Defining Terms

The first thing to accomplish is to make certain that we all understand the goals that this article aims to achieve. When someone says "form-field validation," they mean "validating" or checking the data submitted in a form-field. To be clear, "validation" does not mean making sure that the submitted data is correct in that it is either true or false (ie. validation does not check to ensure that someone named John enters his real name in a form-field. He may enter "Schmoe" or "Cheesehead" as far as the form is concerned), rather it means to ensure that the data is valid in such a way that it falls within certain presupposed parameters. Simply put, it means that when a user is asked to enter their social security number in a field designated to be a social security number, that they will not enter their address or dog's name.

If that is unclear, here is an illustrated example to guide you through that grammatical mess above.

Validation: Incorrect Concept

User's Real Name: "John Doe"

Enter your name:

Validation does not make sure that John Doe enters John Doe, the anonymous nature of the Internet does not give web pages the ability to know and check a user's name, so Iza Goodboy will go through without question.

Validation: Correct Concept

User's Real Name: "John Doe"

Enter your name:

In this case, the web page with form-field validation will catch the fact that the user entered a number instead of a name (which obviously consists of characters not numerals). This example correctly illustrates the concept of form-field validation.

On the next page, we will discuss the first building block of form-field validation, giving the form a memory.


Even Smarter Forms - Page 2

Chris Assenza

September 5, 2000

If you remember the first article in this series then you will remember how we took submitted form data and stored it in variables as follows:

<%
	Dim fname, lname

	fname = Request.Form("First_Name")
	lname = Request.Form("Last_Name")
%>

Assuming the HTML form is using method="post" the, above code takes First_Name and Last_Name in the Forms Collection and stores them in fname and lname respectively. To take it a step further, recall that using a conditional statement, we ensured that the ASP code only executed when the form was submitted and a condition was met. When taken as a whole, it becomes very easy to make a form have persistent memory. If you are confused about what giving a form memory means, it is actually a rather simple concept that you probably see everyday on the Web. Have you ever completed a page of a multi-page form, submitted it, realized you made a mistake on page two, and wanted to go back and fix it? You and everyone else! Well designed sites will save the information you entered in the form until you are completely finished entering the relevant data. All that you need to do in your own web page is add some simple code to the form-field tag. Below is an example of how this would be accomplished with the First_Name above.

<form action="formtest.asp" method="post">
	...
	...
	<input type="text" name="First_Name" value="<%=fname%>">
</form>

Through the use of the value attribute, ASP allows us to literally complete the HTML code before it reaches the client using server-side variables. The great thing about VBScript and ASP in this instance, is that variables do not need to be defined in order to return a value. This fact is important when the page is accessed for the first time before the form is submitted. In such a case, fname will just be empty and value will end up looking like value="" to the client and the form-field will be blank. After the form is submitted for the first time, the server will automatically insert the value of fname in the value, giving your form simple memory!

NOTE: There are other ways to give forms memory. The method we are using will only last as long as the user keeps the browser open and pointed to our site. If we need to save form-field information for later use, we need a more robust and persistent solution. One possibility is to use cookies to store the relevant values. Then, instead of storing submitted form-field data in variables, one would store data taken directly from a Cookies (which in ASP has a collection just like Forms). The input tag would look exactly the same. This method is particularly useful for shopping carts or storing payment information on an e-Commerce site like Buy.com.

To achieve the same effect with a select or checkbox (or any other potentially multi-valued field) you need to do a little more advanced processing. For example, the following code will give a field for "State" memory:

<% state = Request.Form("state") %>
<select name="state">
  <option value="noneSelected">- Select from List -</option>
  <option value="Alabama" 
  	<% if state="Alabama" then response.write("SELECTED") %>>
	Alabama - AL</option>
  <option value="Alaska" 
  	<% if state="Alaska" then response.write("SELECTED") %>>
	Alaska - AK</option>
  <option value="Arizona" 
  	<% if state="Arizona" then response.write("SELECTED") %>>
	Arizona - AZ</option>
  <option value="Arkansas" 
  	<% if state="Arkansas" then response.write("SELECTED") %>>
	Arkansas - AR</option>
  ...
  ...
  <option value="Wyoming" 
  	<% if state="Wyoming" then response.write("SELECTED") %>>
	Wyoming - WY</option>
</select>

Now that you understand how to give your form memory, the first thing to do is go back to your form and implement this functionality now, before doing anything else. This step will be time-consuming to you as a developer, but will make your visitors happier, and that is (should be) a primarily goal of all web developers. Once you have done that, move on to the next page and we will begin talking about actually validating the submitted form data.


Dealing with Blank Fields - Page 3

Chris Assenza

September 5, 2000

The most commonly used and simple need for validation is to ensure that your site visitors do not leave a crucial form-field blank. You could use client-side scripting to prevent this, but not all users will have the right type of browser or JavaScript support enabled. So, to make sure no one slips through the cracks, it is time to use some server-side scripting to accomplish this task. For this example, let us assume that you have a form with First Name, Last Name, Social Security Number, Address, City, State, Zip Code, Telephone Number and Email Address - like this one (feel free to use the source code for this standard form on your own pages):

First Name:
Last Name:
Social Security:
Address:
City:
State
Zip Code
Telephone No.
Email Address

Next, assume that none of the fields can be left blank when submitted. The best thing for you as a developer to do, is to write a small block of code that will check each form-field sequentially. We will accomplish this task with a For...Each loop inside our conditional test that makes sure the form has been submitted. Note: For...Each loops are used in VBScript and ASP to sequentially iterate, or move through, each item in a collection.

<%
const numFields = 9
dim errorArray()
redim preserve errorArray(numFields)

if Request.Form("isSubmitted") then
	...
	...

	ErrorMsg = ""
	x = 0
	For Each formField in Request.Form
		if Len(Request.Form(formField)) = 0 OR Request.Form(formField) 
				= "noneSelected" then
			errorArray(x) = True
			ErrorMsg = ErrorMsg & Ucase(formField) & "<br>"
		else
			errorArray(x) = False
		end if
		x = x + 1
	Next
%>
Note that in the example above we've line-wrapped the code at the equals symbol (=), but in reality the command is one long line.

You are probably thinking that was a pretty big mouthful for such a small request, so let's take a look at what this little block of code does, line by line.

const numFields = 9 is a constant that we set equal to the number of fields in the form we are validating. Using constants is a good practice because if you ever re-use this code elsewhere you can keep everything the same, change the constant, and validate as many fields as necessary.

dim errorrArray() sets up, or declares, an array named "errorArray," whose length is not defined. We will be using this array to store the names of the form-fields that return errors so that they can be referenced later to provide meaningful error messages to your users.

The next line, redim preserve errorArray(x), redefines the size of the array to match the current value of numFields. Remember, this array is where errors are being stored, so it is important that it matches the number of form elements in the collection. The little extra bit of code, preserve, basically makes sure that the array is kept active in memory throughout the rest of the code.

if Request.Form("isSubmitted") then is there only to show you where this code block of code is going in relation to our conditional statement that checks to see if the form is submitted. The two ellipses (...) indicate whatever code you may already have there, like the code that stores the values of the form-fields in variables.

ErrorMsg = "" and x = 0 both initialize variables (ErrorMsg and x, respectively) with a default value of an empty string for ErrorMsg and 0 for x. ErrorMsg is a string that will be used to store an HTML-formatted message displayed on the page when a validation error occurs (more on this later). X is being used as a type of counter that will start at 0 and continue to increase until the For...Each loop is concluded. It will be used to reference specific locations within the array, errorArray.

For Each formField in Request.Form is a special version of a For...Next loop called a For...Each loop that sequences through a collection, in this case our form. On each iteration of the loop, formField will be equal the name of the current form-field in the collection. For example, if the loop is on Zip Code, formField will equal "zip_code" and the this Request.Form(formField) code will return the value of zip_code. Pretty convenient, no?

if Len(Request.Form(formField)) = 0 Request.Form(formField) = "noneSelected" then is a simple conditional statement that asks "If the current form-field has no length (is empty) or is 'noneSelected" for the state field, then do the following..."

errorArray(x) = True and ErrorMsg = ErrorMsg & Ucase(formField) & "<br>" are executed when the previous if statement is found to be "True" or when the value of the current form-field is empty. Thus, the current element of errorArray is set to "True" to denote an error and the ErrorMsg string is set to equal itself (in case this is not the first error) and then adds the name of the form-field that is incorrect.

If the form-field does have a length, or is not empty, then the current element in the errorArray is set to "False" since there is no error to report.

x = x + 1 increments x every time each time the code loops.

Okay, if you have followed that successfully, (if not, email me and I'll help if I can) the next step is to provide some notice to the site visitor that they have submitted an error. This step is actually very easy, we simply add a small conditional test right underneath the body tag (or wherever you want):

...
<body>
	<% if ErrorMsg <> "" then %>
		<font color="red" size="3"><b>
		<%= ErrorMsg %>
		</font><br>
	<% end if %>
	<form name="sample1" method="post">
...

All this code does is ask: "If the ErrorMsg variable is not empty, then there is an error message to tell the user, so I will output it in big red bold text." If there is no value in ErrorMsg then the output is ignored and the form is returned as usual. At this point, you are probably asking what that silly array was for, and now I will tell you. Have you ever seen the forms where the name of the field that was left blank is a different color or bold? We are going to recreate that effect using this array.

If you think this part is going to be hard to do, don't, it is not. All that needs to be done is not unlike what you already did to retain the value for the state field. Before each "caption" for the input fields, you simply need to put, in ascending order (from 0...n) a check to see if the corresponding value of the array is true or not. The following code will show you exactly what to do if that is not clear:

<tr>

	<td><% if errorArray(0) = "True" then %>
	   <font color="red"><b>
		<% end if %>First Name: <% if errorArray(0) = "True" then %>
	</b></font>
		<% end if %>
	</td>
	<td>
		<input name="first_name" 
			size="25" 
			maxlength="50" 
			value="<%= first_name %>">
	</td>

</tr>

<tr>

	<td>
		<% if errorArray(1) = "True" then %>
	   <font color="red"><b>
		<% end if %>Last Name: <% if errorArray(1) = "True" then %>
	   </b></font>
		<% end if %>
	</td>

	<td>
		<input name="last_name" 
			size="25" 
			maxlength="50" 
			value="<%= last_name %>">
	</td>

</tr>
WARNING: In writing this article, I believe I discovered some type of bug or oddity about the ASP compiler. Every form element will be read in sequentially, as they are coded. However, for whatever reason, this particular page grabs City before Last Name. I asked around, and no one is certain why. So, a word of caution to you, although errorArray(1) should be for Last Name, it is actually City, and errorArray(2) is Last Name. Needless to say, if you encounter problems, experiment a bit to see what order the form elements are being processed.
NOTE: The second check of the array after the caption is actually to put in the closing tags for font and bold. However, these really are not necessary. One of the neat things about tables is that, in most browsers, the ending </td> actually ends any formatting within that cell. However, the WDVL believes in compliant code and so, if you want to be correct, close the tags. If not, omit at your own discretion and risk.

If you would like to see this in action, I have set up a demo on Enfused.com. Please note that I added the code to my form so that it has short-term memory of what the user submits.

Once you have played around a bit and tried this stuff yourself (which I might add is the only true way to learn), move on to the next page and we will talk about validating specific fields.


Making Sure People Do Not Enter L33t As Their Name - Page 4

Chris Assenza

September 5, 2000

You now know how to make sure something is at least entered for every field, but what about specific fields? What if you do not care if someone enters their last name but must have them enter a valid first name? Not a problem, this can be accomplished very easily building on the skills you have already acquired reading this article. First, we are going to drop the validation code we used on the last page and do each field individually. There is, of course, a disadvantage to this method in that you cannot easily re-use proprietary hard-coded validation code in other forms you utilize in the future. However, if you are a savvy programmer, there are ways to make everything very general and re-usable. If you just want to check for empty fields, the code we discussed on the previous page will work great for most anything.

Instead of the code on the previous page, try the following instead:

<%
	const numFields = 9
	dim errorArray()
	redim preserve errorArray(numFields)

	if Request.Form("isSubmitted") then
		...
		...
		if Len(last_name) = 0 then
			errorArray(1) = "True"
			ErrorMsg = "Last Name<br>"
		end if
	end if
%>

Rather then going through that line-by-line (since most of it should be familiar to you), let's take a quick look at the code inside the second if...then statement. It says: if Len(last_name) = 0 then, errorArray(1) = "True" and ErrorMsg = "Last Name<br>". As you probably surmised, this little block is hard coded to see if last_name (did you remember to assign Request.Form("last_name") to a variable? I called mine last_name) has any value. If it does not, then element 1 of the errorArray is hard coded as "True" and the ErrorMsg variable is set equal to "Last Name" and an HTML line-break.

That covers last name, but what do we do about First Name, which we have decided is both a required field and one that we must validate to ensure that a valid submission is entered. To begin, start easy and just make sure the field has a value at all by repeating what we did for Last Name.

<%
	const numFields = 9
	dim errorArray()
	redim preserve errorArray(numFields)

	if Request.Form("isSubmitted") then
		...
		...
		if Len(first_name) = 0 then
			errorArray(0) = "True"
			ErrorMsg = "First Name<"
		end if
		if Len(last_name) = 0 then
			errorArray(1) = "True"
			ErrorMsg = ErrorMsg & "Last Name<br>"
			'Note, I added ErrorMsg & to this line to make 
				'sure we keep the whole string
		end if
	end if
%>

That part was easy, now all we need to do is make sure that name is not a number or some other invalid value. To do that, there are a number of options, of which two are most popular: regular expressions and string searching. Regular Expressions are probably something with which you Perl fans are very familiar. It is the life-blood of string-handling and comparison with Perl, as Aaron Weiss points out in his The Perl You Need to Know series. For those who do not know, a Regular Expressions is a pattern that you define with letters, numbers and symbols that is then compared against a string. The computer tries to match this pattern to the same pattern in the string. If a match is found, True is returned, if not False is returned. If that does not sound familiar to you, you have actually probably used Regular Expressions before. Think of when you went to Start >> Find in Windows and entered files of type *.doc. When you did that, you were searching for all files that matched the extension .doc - that is a regular expression. Unfortunately, Regular Expressions are something of a new beast to VBScript for the Web and ASP, and as such, they are handled a bit differently then Perl Regular Expressions. We will discuss this more in a few minutes.

The other option you have is to actually perform more complex string searching on the field, in our case first_name, using string specific functions. Quite honestly, I have had mixed results when trying to use regular expressions in ASP (probably because I learned them in Perl) and as such, I tend to stick to using string functions, even if they are a little less efficient code wise. At any rate, I will show you how to do both with an emphasis on regular expressions because they are far more useful and easy once you have gotten the hang of them.

To begin, we will use some looping and a string function to figure out if first_name has any non-characters in it. To do that, we will need to loop through every character in first_name. We will do that with a for...next loop, like so:

<%
	...
	for y = 1 to len(first_name)
		testVar = mid(first_name, y, 1)
		if (asc(testVar) < 65) or ((asc(testVar) > 90) 
			AND (asc(testVar) < 97)) or (asc(testVar) > 122) then
			errorArray(0) = "True"
			ErrorMsg = "First Name<br>"
			Exit For
		end if
	next
	...
%>
Note that in the example above we've line-wrapped the code at the word AND, but in reality the command is one long line.

Alright, that looks pretty complex, but do not worry, the code is explained line-by-line below.

for y = 1 to len(first_name) starts a for...next loop that loops from one (1) to the length (or to the max number of characters) in first name.

testVar = mid(first_name, y, 1) sets the variable testVar equal to the value returned by the mid funtion performed on the string, first_name. The syntax for mid is mid(string, start, length).

if (asc(testVar) < 65) or ((asc(testVar) > 90) AND (asc(testVar) < 97)) or (asc(testVar) > 122) is a conditional test that converts the value of testVar into its ASCII value. If it is less then 65, in between 90 and 97, or greater then 122, it is not an alphabetic character (for a list of the ASCII characters and their decimal equivalents, check this site out.) If the character is not alphabetic, the code inside the if...then is executed, which is our standard error code. The only change is the Exit For which basically tells the for...next loop to call it quits, since we have already found at least one error.

The only thing left to explain is where this code goes in the grand scheme of things, so check it out below. You will see that it first checks to make sure the field is not blank, then if it is not, it will check for non-alphabetic characters.

<%
	const numFields = 9
	dim errorArray()
	redim preserve errorArray(numFields)

	if Request.Form("isSubmitted") then
		...
		...
		if Len(first_name) = 0 then
			errorArray(0) = "True"
			ErrorMsg = "First Name<br>"
		else 'here is the new code
			for y = 1 to len(first_name)
				testVar = mid(first_name, y, 1)
				if (asc(testVar) < 65) or ((asc(testVar) > 90) 
				AND (asc(testVar) < 97)) or (asc(testVar) > 122) then
					errorArray(0) = "True"
					ErrorMsg = "First Name<br>"
					Exit For
				end if
			next
		end if
		if Len(last_name) = 0 then
			errorArray(1) = "True"
			ErrorMsg = ErrorMsg & "Last Name<br>"
			'Note, I added ErrorMsg & to this line to make 
				'sure we keep the whole string
		end if
	end if
%>
Note that in the example above we've line-wrapped the code at AND, but in reality the command is one long line.

That really was not too bad, but it seems fairly tedious to go through every character with a for...next loop. That is where Regular Expressions come in. If you can get set up and working properly, then they are definitely the way to go, and you will see why in a minute.

For starters, I recommend you check out Microsoft's VBScript Regular Expression Introduction, if you are brand new to the technique (or if you are a very Perl oriented individual). Once you've glanced through that and printed out the Regular Expression Syntax page, study the following code that performs the same thing as our for...next loop above. In fact, this particular Regular Expression kills two birds with one stone by eliminating the need to check for a blank field!

<%
	...
	dim re, results
	set re = New RegExp
	re.Pattern = "^\D+$"
	re.Global = True
	re.IgnoreCase = True
	results = re.Test(first_name)
	if results then
		errorArray(0) = "False"
	else
		errorArray(0) = "True"
		ErrorMsg = "First Name<br>"
	end if
	...
%>

To begin, you must declare the variables re and results (you can name them whatever you want). Then, we invoke the RegExp object in the form of an instance, re.

Following that, it is important to set some parameters for the regular expression. Most importantly is the pattern that will be matched, which is, ^\D+$. If you check out that reference sheet I asked you to print, you will note that \D stands for any non-digit character, while the + tells the Regular Expression to match one or more of these characters. The ^ and $ makes sure it checks and is limited to the whole string. Granted, that means it will not pick up symbols, but that is not necessarily a bad thing if a foreign name is possible. However, if you want to be thorough, try this: re.Pattern = "^[^0-9\/><\.,\\!\^\$\*\+\?@#%&\(\);:\[\]\{\}=""']+$". Yes, that is frightening, but all it says is not (^) 0-9 or any of the symbols following. If there is a backslash before a symbol, that means it has been "escaped." Symbols that represent a behavior in a Reqular Expression must first be escaped if you want to search for them. Whichever you decide to use, if results is found to be true (and the pattern is matched), then there is no error, else there is and we note that with our array and ErrorMsg.

As you can see, while a bit more complex, this is very effective at finding patterns in a string. This feature will make itself more evident when we get into validating specific patterns like social security numbers, telephone numbers, etc. on the next page. If you would like to see Regular Expressions in action, visit this other sample at Enfused. Also, just for your convenience, here is what the code will look like in the whole scheme of things:

<%
	const numFields = 9
	dim errorArray()
	redim preserve errorArray(numFields)

	if request.form("isSubmitted") = "yes" then
		...
		...
		ErrorMsg = ""
		dim re, results
		set re = New RegExp
		re.Pattern = "^[^0-9\/<<\.,\\!\^\$\*\+\?@#%&\(\);:\[\]\{\}=""']+$"
		re.Global = True
		re.IgnoreCase = True
		results = re.Test(first_name)
		if results then
			errorArray(0) = "False"
		else
			errorArray(0) = "True"
			ErrorMsg = "First Name<br<"
		end if
		if Len(last_name) = 0 then
			errorArray(1) = "True"
			ErrorMsg = ErrorMsg & "Last Name<br<"
			'Note, I added ErrorMsg & to this line to make 
				'sure we keep the whole string
		end if
	end if
%>

I do not want to overload you in this tutorial, so on the next page I will guide you through a few more regular expressions for common fields and then we will call it quits so you can go practice.


Regular Expressions - Page 5

Chris Assenza

September 5, 2000

That really was not too bad, but it seems fairly tedious to go through every character with a for...next loop. That is where Regular Expressions come in. If you can get set up and working properly, then they are definitely the way to go, and you will see why in a minute.

For starters, I recommend you check out Microsoft's VBScript Regular Expression Introduction, if you are brand new to the technique (or if you are a very Perl oriented individual). Once you've glanced through that and printed out the Regular Expression Syntax page, study the following code that performs the same thing as our for...next loop above. In fact, this particular Regular Expression kills two birds with one stone by eliminating the need to check for a blank field!

<%
	...
	dim re, results
	set re = New RegExp
	re.Pattern = "^\D+$"
	re.Global = True
	re.IgnoreCase = True
	results = re.Test(first_name)
	if results then
		errorArray(0) = "False"
	else
		errorArray(0) = "True"
		ErrorMsg = "First Name<br>"
	end if
	...
%>

To begin, you must declare the variables re and results (you can name them whatever you want). Then, we invoke the RegExp object in the form of an instance, re.

Following that, it is important to set some parameters for the regular expression. Most importantly is the pattern that will be matched, which is, ^\D+$. If you check out that reference sheet I asked you to print, you will note that \D stands for any non-digit character, while the + tells the Regular Expression to match one or more of these characters. The ^ and $ makes sure it checks and is limited to the whole string. Granted, that means it will not pick up symbols, but that is not necessarily a bad thing if a foreign name is possible. However, if you want to be thorough, try this: re.Pattern = "^[^0-9\/><\.,\\!\^\$\*\+\?@#%&\(\);:\[\]\{\}=""']+$". Yes, that is frightening, but all it says is not (^) 0-9 or any of the symbols following. If there is a backslash before a symbol, that means it has been "escaped." Symbols that represent a behavior in a Reqular Expression must first be escaped if you want to search for them. Whichever you decide to use, if results is found to be true (and the pattern is matched), then there is no error, else there is and we note that with our array and ErrorMsg.

As you can see, while a bit more complex, this is very effective at finding patterns in a string. This feature will make itself more evident when we get into validating specific patterns like social security numbers, telephone numbers, etc. on the next page. If you would like to see Regular Expressions in action, visit this other sample at Enfused. Also, just for your convenience, here is what the code will look like in the whole scheme of things:

<%
	const numFields = 9
	dim errorArray()
	redim preserve errorArray(numFields)

	if request.form("isSubmitted") = "yes" then
		...
		...
		ErrorMsg = ""
		dim re, results
		set re = New RegExp
		re.Pattern = "^[^0-9\/><\.,\\!\^\$\*\+\?@#%&\(\);:\[\]\{\}=""']+$"
		re.Global = True
		re.IgnoreCase = True
		results = re.Test(first_name)
		if results then
			errorArray(0) = "False"
		else
			errorArray(0) = "True"
			ErrorMsg = "First Name<br>"
		end if
		if Len(last_name) = 0 then
			errorArray(1) = "True"
			ErrorMsg = ErrorMsg & "Last Name<br>"
			'Note, I added ErrorMsg & to this line to make 
				'sure we keep the whole string
		end if
	end if
%>

I do not want to overload you in this tutorial, so on the next page I will guide you through a few more regular expressions for common fields and then we will call it quits so you can go practice.


How To Deal With Specific Sequences of Numbers and Characters - Page 6

Chris Assenza

September 5, 2000

This page will focus primarily on validating all the other fields we have somewhat ignored on the previous page, like Social Security, Telephone, Zip Code and the Email Address. Since this article is getting pretty long, I will spend less time explaining and more time showing; however, you should walk away with a lot of useful code and understanding for your own web projects.

Social Security Numbers

To validate a social security field you have to first conceptualize how people are going to enter the data. Most people will probably enter 111-11-1111 or 111111111. Now, you can allow either to be valid or force a specific format. I recommend that if you force a specific format, just make sure you tell your users. Below is a good pattern to use assuming that you are forcing 111-11-1111. It checks for 3 digits (\d{3}), a dash, 2 digits, a dash, and 4 digits. Just insert this code after your code for checking the Last Name.

<%
	...
	re.Pattern = "^\d{3}-\d{2}-\d{4}$"
	results = re.Test(social_security)
	if results then
		errorArray(2) = "False"
	else
		errorArray(2) = "True"
		ErrorMsg = ErrorMsg & "Social Security<br>"
	end if
	...
%>

Zip Codes

Assuming you are in the US, zip codes now have a special format and look like: 11111-1111. However, not all people know the four digit extension; so you had better be sure to make your code accepting of both types. I recommend the following pattern shown in the code below. It is a bit trickier then the other ones we have used so far, so pull out your reference sheet again. \d{5} checks for the first five digits, which is common to both zip codes, whether the user knows the four digit extension or not. The next part in parenthesis is what one would call a nested pattern. (-\d{4})? checks for the dash and four digit extension zero or one times (the question mark ? takes care of that). That is all there is too it!

<%
	...
	re.Pattern = "^\d{5}(-\d{4})?$"
	results = re.Test(zip_code)
	if results then
		errorArray(6) = "False"
	else
		errorArray(6) = "True"
		ErrorMsg = ErrorMsg & "Zip Code<br>"
	end if
	...
%>

Telephone Numbers

Validating a telephone number can get tricky, because there are many ways to properly enter a telephone number. Therefore, for this article, we will force a very normal format of ###-####. If you want to be more accepting, use your imagination and reference sheet to create a more complex pattern to match. Notice how it is not unlike the social security number. Tests for 3 digits, a dash and then 4 digits. Make sure for all these tests that you keep those ^ and $ in there, those will ensure that the full string is matched and no extraneous characters are ignored. (For example, if someone enters 240-4334-343444, that will validate without the $, but if you put the $ in, it will return an error).

<%
	...
	re.Pattern = "^\d{3}-\d{4}$"
	results = re.Test(telephone)
	if results then
		errorArray(7) = "False"
	else
		errorArray(7) = "True"
		ErrorMsg = ErrorMsg & "Telephone Number<br>"
	end if
	...
%>

 

Email Addresses

If you had hoped you would learn how to get a user to give you a real and totally valid email address, I am sorry to dash your hopes, but that will not happen here. A lot can be done to attempt to validate an email address, but it takes some extremely complex matching and you can never be one hundred percent accurate. The following pattern is fairly basic but will suffice for most situations. First, think of the things that are standard to email addresses. There is the @ sign, and a ., that is about it. So, we will work around those to come to a usable solution.

<%
	...
	re.Pattern = "^\w+@\w+\.\w+"
	results = re.Test(email)
	if results then
		errorArray(8) = "False"
	else
		errorArray(8) = "True"
		ErrorMsg = ErrorMsg & "Email Address<br>"
	end if
	...
%>

As you can see, it is not a hugely complex pattern, but it gets the job done. It checks for "word" (A-Za-z0-9_) characters (any number of them, but at least one), the @ sign, any number of word characters, the . (escaped by a backslash \.) and then some more word characters. Make sure you drop the $ from the end, because some email addresses end in something like mail.cc.foo.com. Once you get the hang of this stuff, it will come much easier to you and you can do a great many things. Check out the Enfused sample page to see all of this stuff in action.


A Final Look at the Code - Page 7

Chris Assenza

September 5, 2000

This article has been long and probably a little tough for some of you. If that is the case, I strongly recommend you go try this all on your own for a while. When you get frustrated, start to see how the error messages work, and can debug it pretty well on your own; come back here and re-read this article and you will find that it makes much more sense the second time through. Also, if you get horribly stuck, you can always email me. I cannot guarantee a reply, but I like to help! For those of you who like to see the code in its entirety, here it is for your viewing pleasure. Note: This code is the code that checks specific fields using Regular Expressions, not all fields are validated, but they could be if we wanted to.

<%
	const numFields = 9
	dim errorArray()
	redim preserve errorArray(numFields)


	if request.form("isSubmitted") = "yes" then
		first_name = request.form("first_name")
		last_name = request.form("last_name")
		social_security = request.form("social_security")
		address = request.form("address")
		city = request.form("city")
		state = request.form("state")
		zip_code = request.form("zip_code")
		telephone = request.form("telephone")
		email = request.form("email")


		ErrorMsg = ""
		dim re, results
		set re = New RegExp


		'First Name
		re.Pattern = "^[^0-9\/><\.,\\!\^\$\*\+\?@#%&\(\);:\[\]\{\}=""']+$"
		re.Global = True
		re.IgnoreCase = True
		results = re.Test(first_name)
		if results then
			errorArray(0) = "False"
		else
			errorArray(0) = "True"
			ErrorMsg = "First Name<br>"
		end if


		'Last Name
		if Len(last_name) = 0 then
			errorArray(1) = "True"
			ErrorMsg = ErrorMsg & "Last Name<br>"
		end if


		'SS #
		re.Pattern = "^\d{3}-\d{2}-\d{4}$"
		results = re.Test(social_security)
		if results then
			errorArray(2) = "False"
		else
			errorArray(2) = "True"
			ErrorMsg = ErrorMsg & "Social Security<br>"
		end if


		'Zip Code
		re.Pattern = "^\d{5}(-\d{4})?$"
		results = re.Test(zip_code)
		if results then
			errorArray(6) = "False"
		else
			errorArray(6) = "True"
			ErrorMsg = ErrorMsg & "Zip Code<br>"
		end if


		'Telephone
		re.Pattern = "^\d{3}-\d{4}$"
		results = re.Test(telephone)
		if results then
			errorArray(7) = "False"
		else
			errorArray(7) = "True"
			ErrorMsg = ErrorMsg & "Telephone Number<br>"
		end if


		'Email
		re.Pattern = "^\w+@\w+\.\w+"
		results = re.Test(email)
		if results then
			errorArray(8) = "False"
		else
			errorArray(8) = "True"
			ErrorMsg = ErrorMsg & "Email Address<br>"
		end if
	end if
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
	<title>Form Field Validation Sample</title>
</head>
<body>
	<% if ErrorMsg <> "" then %>
		<font color="red" size="3"><b>
		<%= ErrorMsg %>
		</font><br>
	<% end if %>
	<form name="sample1" method="post">
	<table width="50%" cellspacing="1" cellpadding="0" border="0">
	<tr>
	<td><% if errorArray(0) = "True" then %>
			<font color="red"><b>
		<% end if %>First Name: 
		<% if errorArray(0) = "True" then %>
			</b></font>
		<% end if %></td>
	<td><input name="first_name" 
		size="25" 
		maxlength="50" 
		value="<%= first_name %>"></td>
		
	</tr><tr>
		
	<td><% if errorArray(1) = "True" then %>
			<font color="red"><b>
		<% end if %>Last Name: 
		<% if errorArray(1) = "True" then %>
			</b></font>
		<% end if %></td>
	<td><input name="last_name" 
		size="25" 
		maxlength="50" 
		value="<%= last_name %>"></td>
		
	</tr><tr>
	
	<td><% if errorArray(2) = "True" then %>
			<font color="red"><b>
		<% end if %>Social Security: 
		<% if errorArray(2) = "True" then %>
			</b></font>
		<% end if %></td>
	<td><input name="social_security" 
		size="12" 
		maxlength="12" 
		value="<%= social_security %>"></td>
		
	</tr><tr>
	
	<td>Address:</td>
	<td><input name="address" 
		size="35" 
		maxlength="100" 
		value="<%= address %>"></td>
		
	</tr><tr>
	
	<td>City:</td>
	<td><input name="city" 
		size="25" 
		maxlength="50" 
	value="<%= city %>"></td>
	
	</tr><tr>
	
	<td>State: </td>
	<td>
	<select name="state">
	  <option value="noneSelected">- Select from List -</option>
	  <option value="Alabama" 
	  	<% if state="Alabama" then response.write("SELECTED") %>>
		Alabama - AL</option>
	  <option value="Alaska" 
	  	<% if state="Alaska" then response.write("SELECTED") %>>
		Alaska - AK</option>
	  <option value="Arizona" 
	  	<% if state="Arizona" then response.write("SELECTED") %>>
		Arizona - AZ</option>
	  <option value="Arkansas" 
	  	<% if state="Arkansas" then response.write("SELECTED") %>>
		Arkansas - AR</option>
	  <option value="California" 
	  	<% if state="California" then response.write("SELECTED") %>>
		California - CA</option>
	  <option value="Colorado" 
	  	<% if state="Colorado" then response.write("SELECTED") %>>
		Colorado - CO</option>
	  <option value="Connecticut" 
	  	<% if state="Connecticut" then response.write("SELECTED") %>>
		Connecticut - CT</option>
	  <option value="Delaware" 
	  	<% if state="Delaware" then response.write("SELECTED") %>>
		Delaware - DE</option>
	  <option value="District of Columbia" 
	  	<% if state="District of Columbia" then response.write("SELECTED") %>>
		District of Columbia - DC</option>
	  <option value="Florida" 
	  	<% if state="Florida" then response.write("SELECTED") %>>
		Florida - FL</option>
	  <option value="Georgia" 
	  	<% if state="Georgia" then response.write("SELECTED") %>>
		Georgia - GA</option>
	  <option value="Hawaii" 
	  	<% if state="Hawaii" then response.write("SELECTED") %>>
		Hawaii - HI</option>
	  <option value="Idaho" 
	  	<% if state="Idaho" then response.write("SELECTED") %>>
		Idaho - ID</option>
	  <option value="Illinois" 
	  	<% if state="Illinois" then response.write("SELECTED") %>>
		Illinois - IL</option>
	  <option value="Indiana" 
	  	<% if state="Indiana" then response.write("SELECTED") %>>
		Indiana - IN</option>
	  <option value="Iowa" 
	  	<% if state="Iowa" then response.write("SELECTED") %>>
		Iowa - IA</option>
	  <option value="Kansas" 
	  	<% if state="Kansas" then response.write("SELECTED") %>>
		Kansas - KS</option>
	  <option value="Kentucky" 
	  	<% if state="Kentucky" then response.write("SELECTED") %>>
		Kentucky - KY</option>
	  <option value="Louisiana" 
	  	<% if state="Louisiana" then response.write("SELECTED") %>>
		Louisiana - LA</option>
	  <option value="Maine" 
	  	<% if state="Maine" then response.write("SELECTED") %>>
		Maine - ME</option>
	  <option value="Maryland" 
	  	<% if state="Maryland" then response.write("SELECTED") %>> 
		Maryland - MD</option>
	  <option value="Massachusetts" 
	  	<% if state="Massachusetts" then response.write("SELECTED") %>>
		Massachusetts - MA</option>
	  <option value="Michigan" 
	  	<% if state="Michigan" then response.write("SELECTED") %>>
		Michigan - MI</option>
	  <option value="Minnesota" 
	  	<% if state="Minnesota" then response.write("SELECTED") %>>
		Minnesota - MN</option>
	  <option value="Mississippi" 
	  	<% if state="Mississippi" then response.write("SELECTED") %>>
		Mississippi - MS</option>
	  <option value="Missouri" 
	  	<% if state="Missouri" then response.write("SELECTED") %>>
		Missouri - MO</option>
	  <option value="Montana" 
	  	<% if state="Montana" then response.write("SELECTED") %>>
		Montana - MT</option>
	  <option value="Nebraska" 
	  	<% if state="Nebraska" then response.write("SELECTED") %>>
		Nebraska - NE</option>
	  <option value="Nevada" 
	  	<% if state="Nevada" then response.write("SELECTED") %>>
		Nevada - NV</option>
	  <option value="New Hampshire" 
	  	<% if state="New Hampshire" then response.write("SELECTED") %>>
		New Hampshire - NH</option>
	  <option value="New Jersey" 
	  	<% if state="New Jersey" then response.write("SELECTED") %>>
		New Jersey - NJ</option>
	  <option value="New Mexico" 
	  	<% if state="New Mexico" then response.write("SELECTED") %>>
		New Mexico - NM</option>
	  <option value="New York" 
	  	<% if state="New York" then response.write("SELECTED") %>>
		New York - NY</option>
	  <option value="North Carolina" 
	  	<% if state="North Carolina" then response.write("SELECTED") %>>
		North Carolina - NC</option>
	  <option value="North Dakota" 
	  	<% if state="North Dakota" then response.write("SELECTED") %>>
		North Dakota - ND</option>
	  <option value="Ohio" 
	  	<% if state="Ohio" then response.write("SELECTED") %>>
		Ohio - OH</option>
	  <option value="Oklahoma" 
	  	<% if state="Oklahoma" then response.write("SELECTED") %>>
		Oklahoma - OK</option>
	  <option value="Oregon" 
	  	<% if state="Oregon" then response.write("SELECTED") %>>
		Oregon - OR</option>
	  <option value="Pennsylvania" 
	  	<% if state="Pennsylvania" then response.write("SELECTED") %>>
		Pennsylvania - PA</option>
	  <option value="Rhode Island" 
	  	<% if state="Rhode Island" then response.write("SELECTED") %>>
		Rhode Island - RI</option>
	  <option value="South Carolina" 
	  	<% if state="South Carolina" then response.write("SELECTED") %>>
		South Carolina - SC</option>
	  <option value="South Dakota" 
	  	<% if state="South Dakota" then response.write("SELECTED") %>>
		South Dakota - SD</option>
	  <option value="Tennessee" 
	  	<% if state="Tennessee" then response.write("SELECTED") %>>
		Tennessee - TN</option>
	  <option value="Texas" 
	  	<% if state="Texas" then response.write("SELECTED") %>>
		Texas - TX</option>
	  <option value="Utah" 
	  	<% if state="Utah" then response.write("SELECTED") %>>
		Utah - UT</option>
	  <option value="Vermont" 
	  	<% if state="Vermont" then response.write("SELECTED") %>>
		Vermont - VT</option>
	  <option value="Virginia" 
	  	<% if state="Virginia" then response.write("SELECTED") %>>
		Virginia - VA</option>
	  <option value="Washington" 
	  	<% if state="Washington" then response.write("SELECTED") %>>
		Washington - WA</option>
	  <option value="West Virginia" 
	  	<% if state="West Virginia" then response.write("SELECTED") %>>
		West Virginia - WV</option>
	  <option value="Wisconsin" 
	  	<% if state="Wisconsin" then response.write("SELECTED") %>>
		isconsin - WI</option>
	  <option value="Wyoming" 
	  	<% if state="Wyoming" then response.write("SELECTED") %>>
		Wyoming - WY</option>
	</select>
	</td>
	
	</tr><tr>
	
	<td><% if errorArray(6) = "True" then %>
			<font color="red"><b>
		<% end if %>Zip Code: 
		<% if errorArray(6) = "True" then %>
			</b></font>
		<% end if %></td>
	<td><input name="zip_code" value="<%= zip_code %>"></td>
	
	</tr><tr>
	
	<td><% if errorArray(7) = "True" then %>
			<font color="red"><b>
		<% end if %>Telephone No.: 
		<% if errorArray(7) = "True" then %>
			</b></font>
		<% end if %></td>
	<td><input name="telephone" value="<%= telephone %>"></td>

	</tr><tr>
	
	<td><% if errorArray(8) = "True" then %>
			<font color="red"><b>
		<% end if %>Email Address: 
		<% if errorArray(8) = "True" then %>
			</b></font>
		<% end if %></td>
	<td><input name="email" value="<%= email %>"></td>
	
	</tr><tr>
	
	<td colspan="2">
		<input type="submit" value="Submit">
		<input type="hidden" name="isSubmitted" value="yes">
	</td>
	
	</tr>
	</table>
	</form>
</body>
</html>

Conclusion

In this article we discussed using Microsoft's Active Server Page technology to validate user-submitted form data. With this knowledge, which includes Regular Expressions, for...each looping, string manipulation, and adding simple memory to forms, you are well on your way to creating better web pages. The potential uses for this particular set of technological understanding are limitless, particularly in an e-Business/Commerce environment!


Part 3 - Building a Registration Database

Chris Assenza

October 16, 2000

 

If you have been following along in this series and read about how to use Microsoft Active Server Pages to make your forms functional, interactive, smart and valid, then the next logical step is to do something a little more permanent with the data. Sending an email is fine, but if you are building something like an online registration database for internal marketing purposes or for allowing repeat access to features on your site, then you'll need to put that data in a database.

To follow along in this article, you will need to have a thorough understanding of the techniques discussed in the two other articles in this series. You will also need access to some type of ODBC (Open Database Connectivity) compliant database package. I will be using Microsoft Access 2000 on Windows 98, but you can use Windows 2000/NT/9x if you so choose.

The Scenario

Before delving right into the meat of this topic, it is important to define a framework within which we will be working. Technology is best used as a means to an end, so we will develop a working and practical (albeit small) registration system. This registration system will collect demographic information about the site visitor, as well as a username and password they select, so they may access subscription based services on your site.

An example can be seen on Enfused's Registration Page, although we won't go into so much detail. We are also going to assume that you don't need some detailed registration agreement, which you can easily implement at another time. Read the contents of that page, or just skip and click "I AGREE" and you will see the front-end of what we will be recreating on a generic basis.

In addition, please go back to the article on form-field validation and grab the code on the final page, we will be building off of that page to complete our registration system. Note: If you want to save time, I have prepared a zip file including the database and files we will be working with. You can download it now and just follow along if you want.

Finalizing the Form

Chris Assenza

October 16, 2000

Adding a Username and Password to the Form

The nice thing about generic designs is that they are re-usable, which saves a lot of headache and a lot of coding if done correctly. Since the data we need to collect is already ready to go in our existing form, we need only add some logic for a username and password. I think adding them to the top of the form is most appropriate, so in an abbreviated format, here is what it should look like:

<%
const numFields = 11
'change the above from 9 to 11
dim errorArray()
redim preserve errorArray(numFields)


if request.form("isSubmitted") = "yes" then
	'add username and password here
	username = request.form("username")
	password = request.form("password")
	first_name = request.form("first_name")
	last_name = request.form("last_name")
	social_security = request.form("social_security")
	address = request.form("address")
	city = request.form("city")
	state = request.form("state")
	zip_code = request.form("zip_code")
	telephone = request.form("telephone")
	email = request.form("email")
	'the rest of your ASP goes here...
%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Form Field Validation Sample</title>
</head>
<body>
<% if ErrorMsg <> "" then %>
	<font color="red" size="3"><b>
	<%= ErrorMsg %>
	</font><br>
<% end if %>
<form name="sample1" method="post">
<table width="50%" cellspacing="1" cellpadding="0" border="0">
<!-- NEW CODE GOES HERE -->
<tr>
<td>
	<% if errorArray(9) = "True" then %>
		<font color="red"><b>
	<% end if %>Username:
	<% if errorArray(9) = "True" then %>
		</b></font>
	<% end if %>
</td>
<td>
	<input name="username" size="10"
	maxlength="10" 	value="<%= username %>">
</td>
</tr>
<tr>
<td>
	<% if errorArray(10) = "True" then %>
		<font color="red"><b>
	<% end if %>Password:
	<% if errorArray(10) = "True" then %>
		</b></font>
	<% end if %>
</td>
<td>
	<input type="password" name="password"
	size="10" maxlength="10">
</td>
</tr>
<!-- END NEW CODE -->
<!-- RESUME REST OF OLD CODE -->

Some things to note in the above code. First and foremost, remember to change the number of required fields assigned to the constant numFields. That is very important for validation, because it defines how many elements will be in the errorArray. Also note that rather then renumbering everything, we are merely tacking two elements on the end for Username and Password. It does not matter if they appear first or last in the actual HTML for the form. Lastly, we need to discuss how we will validate this information. There are a number of considerations to take into account. First, neither username nor password can be left blank. Second, username should be greater then four characters and can be made up of alphanumeric characters. Password must be at least eight characters long and can also be made up of alphanumeric characters. Third, username cannot be the same as a username already stored in the database. For now, we can easily deal with the first two considerations, but until we learn about how to talk to the database, the third will have to wait.

To be consistent, I recommend using regular expressions to validate the username and password. However, do not feel required to do so, any way you think up that is best for you will do fine. The two blocks of code shown below both utilize regular expression patterns that check for \w or any alphabetic or numeric character (including underscore). It checks for four characters in the case of username and 8 in the case of password. Note that the $ was omitted from the end of the pattern so that it does not match against the whole field globally - that means a user can have a larger username then four if they want - up to the maximum length of the input field. Again, I will leave it up to you to spruce up things like the error message (ErrorMsg).

'...
'Username
re.Pattern = "\w{4}"
results = re.Test(username)
if results then
	errorArray(9) = "False"
else
	errorArray(9) = "True"
	ErrorMsg = ErrorMsg & "Username<br>"
end if


'Password
re.Pattern = "\w{8}"
results = re.Test(password)
if results then
	errorArray(10) = "False"
else
	errorArray(10) = "True"
	ErrorMsg = ErrorMsg & "Password<br>"
end if
'...

NOTE: Do not forget to modify the ErrorMsg code for First Name. It should now look like ErrorMsg = ErrorMsg & "First Name<br>". You need to do this so that if there is an error for Username or Password, those will show up in the message. If you omit this, Username and Password will be highlighted red, but will not be included in the list at the top of the page!

All right, now that the username and password are squared away (at least for the time being), move on to the next page and we will talk about setting up the database.

Web Databases 101

Chris Assenza

October 16, 2000

Setting up the Database

To get the database set up is actually not a very complex task if you understand Microsoft Access and are comfortable playing with Windows settings from the Control Panel.

The first thing you need to do is start Access (or whatever you are using) and create a new database. Store the database wherever you like and call it something simple and memorable, like registration_db. Next, create a new table and call it something like tlb_users. Build the table using design view so you can set the constraints for the fields. Make sure each field is named appropriately to reflect the data being collected by the form. Also, be sure to assign a primary key - just make up an auto-number field for that. Finally, make certain that you properly set the constraints for each field - primarily field lengths. If you have address with maxlength="100" then your database should also allow for 100 characters in the address field. If you don't want to fool around with making this database, you can download the one I made. For those of you who want to take the pure do-it-yourself approach, here is a screenshot of my tbl_users.

tbl_users Screenshot

If you are totally lost at this point, I do not recommend you go forward. At the bottom of this page, I will provide some links to Access and relational database tutorials so you can get up to speed. Once you have read those, come back and try again! It will take some time to get a handle on all of this though, if you are fairly new to these concepts and techniques.

Making the Database Accessible Via the Web

The next thing you need to do is make the database accessible to your web page. To do that, you will have to set up a DSN (data source name) in the ODBC settings found inside the Windows Control Panel. A data source name is something you configure that will store information about how to connect to the database using ODBC (Open Database Connectivity - basically a driver that enable one to send SQL commands to a database management system, from outside the system itself - like via a web page).

Windows makes setting up a DSN fairly easy and painless - all you need to know is the name of your database and where it is on your hard drive. Please note that you are going to have to have some administrative privileges to do this if you are on an NT server. If you are working with a third party web host, you will need to contact them and ask them to set it up for you. With Windows 9x and Personal Web Server, you can set it up on your own!

First, go to Start > Settings > Control Panel. Then click on "Data Sources" (if NT) or "ODBC Data Sources" (if Windows 9x). Then, click on the System DSN tab. Click Add... and select the database type you are using - for Access users that is Microsoft Access Driver (*.mdb). Enter something simple for the data source name and remember what you enter; you will need it when we add the necessary logic to the web page. Description you can leave blank or fill in, it is not really necessary. Next, where you see a row of buttons under the heading Database, click the Select button. Browse through your hard drive and find the database you created or downloaded. Then, select it, click OK and then click OK again on the original screen. You will see that screen disappear, but will notice that there is now something in the list on the System DSN tab - that is the database you just set up, identified by the name you assigned in the dialog box.

DSN Setup Screenshot

Believe it or not, that is it, we are ready to go back to the code and make this work! On the next page we will discuss just how we will get the web page to talk to the database, via ODBC.

ADO is Our Friend

Chris Assenza

October 16, 2000

Microsoft's ActiveX Data Objects

Microsoft was both kind enough and wise enough to include a means of talking to various data sources by including ActiveX Data Objects (aka ADO) with ASP. ADO will allow the developer to connect to an ODBC data source (what you set up on the last page), and, using special methods specific to ADO, send SQL commands to the data source. We will not be taking an exhaustive look at ADO for this article, because that would take a few articles in and of itself, we are just going to use it so we can get the job done - which is all most of us probably care about. If you are the type of person with an insatiable hunger to be a technical mastermind, check out the links at the bottom of this page for all the untold details.

The ADO Object Model*

There are a number of objects within the ADO model, they are:

Each of these objects has a number of properties and methods - most of which we will not even take a look at. As a matter of fact, forget all about Error, Command, Parameter and Field - we will not need those for what we are going to do. Instead, let's start with Connection, the object needed to get our web page talking to the database.

Connection does exactly what you think it would do, establishes a connection to the database, via something called a Connection String. To start, as with any other object, you must invoke an instance of it. This act is a simple one and requires that you declare a variable and then create the object on the server, like so (assuming conn is the name of the declared variable): set conn = Server.CreateObject("ADODB.Connection"). Once you have invoked the object, it is important to set the necessary properties in order to successfully talk to your database. The most important one at this point is the Connection String.

A typical Connection String will consist of the DSN for the database, and possibly the username and password to the database (if you assigned them). The syntax is: ConnectionName.ConnectionString = "dsn=DSN You Assigned[;user=Username;password=Database Password]" (Note: Code inside brackets is optional, the brackets themselves are not part of the syntax).

The following block of code is what a completed Connection would look like for our example registration system. I will explain all the code line-by-line below: (Note: This structure is not exactly how it appears in the final version of this particular project - the declarations and instance creation are done earlier on at the top of the page - I have illustrated what I mean on a subsequent page).

dim conn, strSQL, rst
set conn = Server.CreateObject("ADODB.Connection")
conn.ConnectionString = "dsn=wdvl_test"
strSQL = "SELECT * FROM tbl_users;"
	set rst = Server.CreateObject("ADODB.Recordset")
	rst.Open strSQL, conn, 3, 3

Not bad, right? dim conn, strSQL, rst is code you should be familiar with by now, this line declares variables called conn, strSQL and rst as type Variant. conn will be used for our Connection object, strSQL will be used for a line of SQL (Structured Query Language), and rst is going to be used for a Recordset, which I will explain momentarily.

set conn = Server.CreateObject("ADODB.Connection") invokes an instance of the ADODB.Connection on the server, allowing the developer to establish a connection to the database, as outlined in a preceding paragraph.

conn.ConnectionString = "dsn=wdvl_test" sets the ConnectionString property equal to the DSN we setup for the database on the previous page. Since we did not add any security features to the database, the optional user and password parameters were dropped.

On the next page we will discuss the next few lines of code, starting with a very brief look at SQL.

ADO References
LearnASP.com: ADO Table of Contents
ASP101: ADO 2.0 Reference
15 Seconds: A Practical Introduction to ADO
MSDN: The ADO Object Model

Print:
QUE: Using ASP Special Edition * This book helped me with this article! Definitely worth a look! (And no, I do not work for QUE).
WROX: Beginning ASP Databases

SQL and Recordsets

Chris Assenza

October 16, 2000

Basics of SQL

SQL, or Structured Query Language, is the standard way of communicating with relational databases. Even though you do not know it, everything you do with the Microsoft Access GUI (like declare field names or build a query) is actually being done with SQL behind the scenes. For instance, when you create a new table in Access, the DBMS (Database Management System - ie. Access in this case) actually goes behind the scenes and uses the CREATE TABLE SQL command to create the table you specified. So, while it is not imperative that you learn every bit of SQL that exists, you should learn the fundamental commands. This is not an SQL tutorial, so I cannot teach you all of them, but we will go over what you need to get the job done, the SELECT command. Again, there are links at the end of this page for those who want to or need to learn more.

The nice thing about SQL is that, unlike other programming languages, you do not need to tell it how to extract data - you simply tell it what you want and it handles the rest. Because it is simpler, more english-like and focuses on "what" one needs to extract from the system, it is called a 4GL language (C++ and others are called 3GL). You may never need to know that, but if you are ever with programmers, you can try to look hip by flashing that little tidbit of knowledge.

As you can tell, unless you are trying to do something pretty advanced, SQL is a fairly easy language. There are a few syntactical things you should know before we examine the SELECT statement. First, there is not any "correct" format for SQL. A statement can be four lines long or one long line - SQL does not care. Second, there is no one "correct" way to use SQL commands, you can use them ALL CAPS or no caps, that is up to you, I prefer to make them ALL CAPS so I can distinguish between the command and the stuff that follows after. I also prefer to write each command per line, as you will see in the next paragraph. Please note, SQL is extremely picky about case with field names - they have to match whatever case you used in the database definition! Third, SQL is not very space sensitive. As long as you put one space in between parameters and commands, SQL is fine. If you want to put tabs, 20 spaces or whole lines, go ahead, SQL does not care. Finally, SQL statements are terminated by a semi-colon. That really is all you need to know to dig right in.

SELECT Statements

"SELECT" is a very powerful SQL command, because with it, one is able to query (or request information) from the database. We will be using SELECT exclusively for the registration database scenario - and not even anywhere close to its full potential. Let's take a look at where we left off on the code from the previous page.

dim conn, strSQL, rst
set conn = Server.CreateObject("ADODB.Connection")
conn.ConnectionString = "dsn=wdvl_test"
strSQL = "SELECT * FROM tbl_users;"
set rst = Server.CreateObject("ADODB.Recordset")
rst.Open strSQL, conn, 3, 3

strSQL = "SELECT * FROM tbl_users;" is about as simple of an SQL command you can get! SELECT statements are composed of the SELECT, followed by a list of field names you want to select, followed by FROM (more SQL syntax) and then the name of a table or another query from which you wish to pull the data. In this line, * is used the same way it is used by Windows - as a wildcard. When you use the asterisk in SQL, you are telling the DBMS to select all of the fields from the designated table, which is tbl_users in this example. Because we are not talking to the database directly, we assign the whole command to a variable, strSQL, which will later be sent to the database by ADO.

Now, for example's sake, let's say you just want to access the first name and email addresses of your registrants, perhaps to send out an important announcement later on. Also, we should probably order those names alphabetically from A to Z. Here is how you would do it:

SELECT First_Name
FROM tbl_users
ORDER BY First_Name;

Simple stuff! We told it what field name (note case-sensitive), what table and used "ORDER BY field_name" to sort the results from A to Z. To order them from Z to A, simply tack on a DESC (for descending) to the end of the ORDER BY line. Now suppose you wanted ADO to have that SQL command. We have not talked about sending that command to the database, but you should store it as a string in some variable to keep your code clean, but how is it possible to store three lines in one variable? You can do three things. One, crunch the SQL up into one line (strSQL = "SELECT First_Name FROM tbl_users ORDER BY First_Name;"). Two, store each line separately in strSQL, by combining strings each time:

strSQL = "SELECT First_Name " <-- note the space before the quote, 
			that is not a typo, but correct syntax.
strSQL = strSQL & "FROM tbl_users "
strSQL = strSQL & "ORDER BY First_Name;"

Or, third, you can make the string run three lines long, as illustrated by the following code:

strSQL = "SELECT First_Name " & _
	 "FROM tbl_users " & _
	 "ORDER BY First_Name;"

You can pick whichever one suits you best when working with ADO in the future. One thing I did not answer at this point is why we need all the fields in our SQL statement. The answer is due to the fact that we need some sort of outline, if you will, of the data we will be manipulating - which leads us to the ADO Recordset.

 

Recordsets are Good

A Recordset is basically a picture of the database, drawn by you, that can be used to manipulate data in the data source. By using the SQL statement we created above and then making a Recordset based off of it (consider the SQL statement the blue-print for the Recordset), a snapshot of the entire tbl_users is created and made available to the web page. Creating a Recordset is about as simple as a Connection, with a few more parameters.

set rst = Server.CreateObject("ADODB.Recordset") invokes an instance of the Recordset object. To actually use the Recordset, you need to define some parameters with the Open method of the Recordset object, not much unlike ConnectionString for the Connection object.

rst.Open strSQL, conn, 3, 3 opens a Recordset using the SQL stored in strSQL, the connection defined by conn, a dynamic cursor (the first 3 - more later), and an optimistic lock (the second 3).

If you can make it through this, you will have made it through the hardest part! Let's take a closer look at that Open method. The first part is fairly obvious, it needs to know a blue-print for how to build the Recordset, and that is our SQL stored in strSQL. Next, the Open method needs to know where the database is and how to connect to it - that is where our friend, conn comes in. This instance of the Connection object will give the Open method all the info it needs to create the appropriate Recordset.

The next two are a bit more vague, but understandable. Recordsets use cursors to navigate through the data they represent. Think of the cursor like a little arrow that points to where one is currently operating within the Recordset. For instance, when first opened, the Recordset's cursor points to the first record (or table row) in the set. If you do some manipulation and move to the next record (or row) then the cursor moves there as well. ADO has four cursor types which all behave in different ways. You really do not need to know those for this particular task, but know that we are using the most common one - the dynamic cursor. It allows us to read or write to any record within the set, whether the cursor is currently pointing to it or not. In other words, it allows us to jump around the set and also see changes made by other users as they occur.

The final parameter tells the Open method how it should handle record locking - or how record/rows should be dealt with when multiple people are acting on the database at the same time. Remember, this is going to be on a web site where many users may be looking at the same exact page at the same exact time, it is important that the data maintain its integrity through it all! There are four types of record locks, but again, you do not need to know those right now (see the links below for references). What you do need to know is that we are using optimistic locking (3), which means that records are only locked to other users when they are being updated/modified.

Move onto the next page and we will put this all together and have a working page!

SQL References
WDVL: Simple SQL - Getting Started with SQL
WDVL: Retrieving and Manipulating Data
SQL Tutorial
Database Central: SQL Resources

Writing the Data to the Database

Chris Assenza

October 16, 2000

Finishing the Job with ADO

All that remains is to get this data actually written to the database. Before we move on to that, in case you did not know, you should put the ADO related code we have been talking about around the validation code, like so:

	if request.form("isSubmitted") = "yes" then
		dim conn, strSQL, rst
		set conn = Server.CreateObject("ADODB.Connection")
		conn.ConnectionString = "dsn=wdvl_test"
		set rst = Server.CreateObject("ADODB.Recordset")


		'...All the stuff in between...


		'Email
		re.Pattern = "^\w+@\w+\.\w+"
		results = re.Test(email)
		if results then
			errorArray(8) = "False"
		else
			errorArray(8) = "True"
			ErrorMsg = ErrorMsg & "Email Address<br>"
		end if


		'One of the problems with the original page is that
		'it doesn't do anything with the form after it's validated!
		'We add a check for ErrorMsg here (to ensure no errors)
		'and then we actually do something with the data!
		if ErrorMsg = "" then
			strSQL = "SELECT * FROM tbl_users;"
			rst.Open strSQL, conn, 3, 3
			'There will be more to come here!
		end if
	end if
%gt;


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
Etc...

Writing the data to the database is a simple matter that involves a few ADO Recordset methods and a little manipulation. First, you need to know how to add a new record to the database. In Access you would just move to the next line in Datasheet view and just start typing. On the web you need to specifically tell it to create the new record. This task is done using the AddNew method of the Recordset and looks like this: rst.AddNew. Following that easy command, you will need to match up the database's field names to the web pages stored versions of the data being submitted. If that does not make sense, look at the following example:

'...
rst("First_Name") = first_name
'etc...

The rst("Field_Name") on the left-hand side of the equals sign is a reference to the database field "First_Name" being made through the Recordset we created. The variable on the right side of the equals sign is the one created by the web page and assigned the value of Request.Form("first_name"). You will need to do this for each database field in the Recordset you created. Once you are done, you need to commit those changes to the actual data source, which is done by adding in the code: rst.Update. That is it! The record is added into the database!

Conclusion

Chris Assenza

October 16, 2000

One Last Pass on the Code

Just to make sure everyone is clear, the following block of code is all the ADO related stuff (minus initialization) we did and where it fits in the page. The validation and HTML form code was omitted because that has not really changed. Also, I added a confirmation message so that the user knows his/her submission was successful.

'The last field validated sits above this block...
if ErrorMsg = "" then
	strSQL = "SELECT * FROM tbl_users;"
	rst.Open strSQL, conn, 3, 3


	'Now write the data.
	rst.AddNew
		rst("Username") = username
		rst("Password") = password
		rst("First_Name") = first_name
		rst("Last_Name") = last_name
		rst("Social_Security") = social_security
		rst("Address") = address
		rst("City") = city
		rst("State") = state
		rst("Zip_Code") = zip_code
		rst("Phone") = telephone
		rst("Email") = email
	rst.Update


	'The next four lines are not necessary but help improve
	'server performance by clearing up memory.
	rst.Close
	conn.Close


	set rst = nothing
	set conn = nothing


	'Making ErrorMsg act like a confirmation message!
	ErrorMsg = "Your submission was successful, thanks for registering!"


		end if
	end if
%>
HTML Etc...

Doh! What About Duplicate Usernames?

Thought I forgot, did you? Well it is true, I almost did, but here we are anyway! Cracking down on repeat usernames is as easy as writing to the database - the only problem is that it is going to restructure part of our page a little, so pay close attention. Way back in the validation section we need to query the database to see if the username already exists. So, let's add the following snippet of code up there:

'...
'Username
re.Pattern = "\w{4}"
results = re.Test(username)


if results then
	strSQL = "SELECT Username FROM tbl_users;"
	rst.Open strSQL, conn, 3, 3


	while not rst.EOF
		if rst("Username") = username then
			duplicate = "True"
		end if
		rst.MoveNext
	wend
	if duplicate = "True" then
		errorArray(9) = "True"
		ErrorMsg = ErrorMsg & "Username<br>"
	else
		errorArray(9) = "False"
	end if


	rst.close
	'Make sure you close the recordset or you will get an error
	'when you try to open it below with a different strSQL.
else
	errorArray(9) = "True"
	ErrorMsg = ErrorMsg & "Username<br>"
end if
'...

All that we are doing is saying, "Hey, if the username matches the criteria, let's make sure it is not already in the database. If it is, let's make the array value true and send back an error, if not, we are good to go!" We do it this way because we do not care about matching it to the database if it does not pass the regular expression, that username could not possibly be in there anyway! Also, that while loop is pretty easy to use. All it does is iterate through each record in the Recordset until it comes to the EOF, or End Of File.

You Did It!

Believe it or not reader, we are done! Mission accomplished, database connected, updated and user satisfied! Of course, there is so much more that you can do with ADO. It is an extremely useful and powerful component within the ASP framework. If you want to get daring you can look up more about ADO from some of the resources I provided and start dealing with time outs, transaction-based processing and all sorts of other neat stuff! Do not forget to download the source code and database if you do not want to do it yourself and as always, Feel free to email me with questions. See you next month!

Using ASP for Form Handling: Part 4 - Filling the Gaps

Chris Assenza

November 13, 2000

 

In this final installment of ASP Form Handling, Chris Assenza discusses such topics as handling radio buttons and check boxes, emailing attachments with CDONTS, and some ways of using the data stored in the registration database we created last month.

Introduction

This month's article marks the end of our discussion of ASP Form Handling. Hopefully you have fully understood everything we have done thus far (and if you are new to this series, welcome aboard, check out the first article). In this article, we are going to cover a number of miscellaneous topics related to all the techniques discussed in previous articles. Some of these topics come straight from questions I received via email (thanks readers) and include: handling radio buttons and check boxes, emailing attachments with CDONTS, sending HTML in an email message, and some ways of using the data stored in the registration database we created last month. Let's start on the next page by revisiting Form Handling techniques.

Contents:

Forms: Saving State Revisited
Advanced CDONTS Techniques
Using the Registration Database
Sending Mass Emails to Subscribers

Forms: Saving State Revisited

Chris Assenza

November 13, 2000

A number of readers have inquired about how to save the state of radio buttons and checkboxes. The technique for accomplishing this is no different then saving the state of a drop-down or select box. Let us assume that you have coded a form that has two sets of radio buttons, a few checkboxes and a drop-down box, like so:

Radio Group 1, Option 1
Radio Group 1, Option 2
Radio Group 1, Option 3

Radio Group 2, Option 1
Radio Group 2, Option 2
Radio Group 2, Option 3

Checkbox 1
Checkbox 2
Checkbox 3

Now, assume that the user has just submitted the form but they made a mistake on some field (not shown) and you want to give them the form again, but do not want to have them fill everything back out, you know the concept by now. Well, here is how:

<%
'pretend we've got the code to check if 
'the form's been submitted here
'now let's assign the form data to some variables

radio_group1 = request.form("r1")
radio_group2 = request.form("r2")
checkbox1 = request.form("cb1")
checkbox2 = request.form("cb2")
checkbox3 = request.form("cb3")
select_opt = request.form("select_example")
%>


<!--html code down to form-->


<form>
<input type="radio" name="r1" value="r1"
<% if radio_group1 = "r1" then %> <%= selected %>
<% end if %>>
Radio Group 1, Option 1<br>
<input type="radio" name="r1" value="r2"
<% if radio_group1 = "r2" then %> <%= selected %>
<% end if %>>
Radio Group 1, Option 2<br>
<input type="radio" name="r1" value="r3"
<% if radio_group1 = "r3" then %> <%= selected %>
<% end if %>>
Radio Group 1, Option 3<br>
<br>
<input type="radio" name="r2" value="r1"
<% if radio_group2 = "r1"then %> <%= selected %>
<% end if %>>
>Radio Group 2, Option 1<br>
<input type="radio" name="r2" value="r2"
<% if radio_group2 = "r2" then %> <%= selected %>
<% end if %>>
Radio Group 2, Option 2<br>
<input type="radio" name="r2" value="r3"
<% if radio_group2 = "r3" then %> <%= selected %>
<% end if %>>
Radio Group 2, Option 3<br>
<br>
<input type="checkbox" name="cb1" value="cb1"
<% if checkbox1 = "cb1" then %> <%= selected %>
<% end if %>>
Checkbox 1<br>
<input type="checkbox" name="cb2" value="cb2"
<% if chekcbox2 = "cb2" then %> <%= selected %>
<% end if %>>
Checkbox 2<br>
<input type="checkbox" name="cb3" value="cb3"
<% if checkbox1 = "cb3" then %> <%= selected %>
<% end if %>>
Checkbox 3<br>
<br>
<select name="select_example">
<option name="o1" value="o1"
<% if select_opt = "o1" then %> <%= selected %>
<% end if %>>
Select Option 1</option>
<option name="o2" value="o2"
<% if select_opt = "o2" then %> <%= selected %>
<% end if %>>
Select Option 2</option>
<option name="o3" value="o3"
<% if select_opt = "o3" then %> <%= selected %>
<% end if %>>
Select Option 3</option>
</select>
</form>

Now that sure is a mess, but fear not, it really is very simple. We need only to dissect one part of that code and you will understand all of it, if you do not already.

Let's take a look at the first radio group and the first option in that group.

<input type="radio" name="r1" value="r1" 
	(note I dropped the >)
<% if radio_group1 = "r1" then %> 
<%= selected %>
<% end if %>> (and put it here)
Radio Group 1, Option 1<br>

The first thing to note is that we had to put the code on multiple lines, everything from the <% if ... to the <% end if %> can be placed on one long line. In fact, I recommend it because it is more legible and easier to work with. Please also note that I dropped the closing > after the value attribute, and put it after the end if. But how does it work? Well, that is the easy part. The if statement checks the value stored in the variable "radio_group1" and compares it to the value of the current option. If the two are equal, then that particular option within the group is marked as "Selected." If the two values do not match, then the ASP code does not do anything. Unless the user did not pick anything the first time the form was submitted, one of the options in the group will be selected because one if statement will be found true! Checkboxes work the same way, they just are not grouped like radio buttons - think of them each as unique items or if it makes more sense, radio buttons with a maximum of one option. Lastly, selects work exactly like radio buttons as well - compare the variable to the option values. On the next page, we will take a more advanced look at CDONTS.

Advanced CDONTS Techniques

Chris Assenza

November 13, 2000

Sending Attachments with CDONTS

Let's say you have your registration web page completed and want to send the user a confirmation email with some standard attachments about rules, procedures and policies associated with registration at your site. If you understood CDONTS from the first article, this task should not be too challenging. However, we never really discussed sending an attachment, like a MS Word document, so here we go.

<%
'pretend we've got all sorts of ASP code 
'up here to handle the form data
'begin CDONTS code


dim objCDO
Set objCDO = Server.CreateObject("CDONTS.NewMail")


objCDO.To = email '(variable we stored the user's email in)
objCDO.From = "someaddy@email.com"
objCDO.Subject = "Confirmation Email"
objCDO.Body = "Thank you for registering."


objCDO.AttachFile ("c:\reg_confirm.doc")


objCDO.Send


'rest of the web page and ASP below.
%>

That is pretty easy, and does not require much explanation. You simply say "AttachFile" and in parenthesis show where the file is on your web site's server. Attaching a file from the client's hard drive is much more complex and a bit out of the scope of this article. You need to deal with A) Putting a field on the form for the file, B) Getting the file from the user's hard drive to your web server, and C) Getting the file from the web server to your inbox. ASP does not support file uploading in forms by default, so you will need a third party component to get the job done (if you want to try this yourself, I recommend EZsite Upload - if you can figure that out, you'll be able to figure the rest out for yourself).

Sending HTML with CDONTS

Some readers were not clear about how to send HTML in an email using CDONTS, perhaps to send a more visually provocative opt-in advertisement or something like that. Fortunately, we can accomplish this task with ease. Let's revisit the code above and discuss how.

<%
'pretend we've got all sorts of ASP code 
'up here to handle the form data
'begin CDONTS code


dim objCDO
Set objCDO = Server.CreateObject("CDONTS.NewMail")


objCDO.To = email '(variable we stored the user's email in)
objCDO.From = "someaddy@email.com"
objCDO.Subject = "Confirmation Email"
objCDO.BodyFormat = 0
objCDO.MailFormat = 0


bodyHTML = "<html><head></head><body>" & _
"<font face=""3"" color=""red"">" & _
"Hello, I'm an a message sent via HTML</font><br><br>" & _
"<img src=""http://www.enfused.com/images/net216.jpg"">" & _
"</body></html>"


objCDO.Body = bodyHTML


objCDO.Send


'rest of the web page and ASP below.
%>

Look carefully at the code above, the first thing you should notice is that we added objCDO.BodyFormat = 0 and objCDO.MailFormat = 0 . Instead of setting these equal to 1, like we did in the first article, this time they have been set equal to 0. Those attributes will tell CDONTS to send the mail as HTML. As for the body of the HTML message, it is literally an HTML page that you can create any way you like. But there are a few caveats of which you must be aware. First, assigning HTML code to a variable requires creative use of quotation marks. Note that all the HTML code is inside double quotes already, so if you have an attribute that uses a double quote, how can one enter it without terminating the original quote? Simply use two quotes like I did above. That will indicate to the server that you want a quote actually embedded within the variable, not that you are terminating the string. If you forget to do this for attributes with quotes, you will get errors, so be careful.

Second, take a look at how we stored all the HTML in one variable. You will recall seeing this technique before when we discussed SQL, at the end of the line if you add & _ you can then continue the string on the next line without worrying about writing "bodyHTML = bodyHTML +" every line. Third, note that the image embedded in this email is pointing to an HTTP location. If you think about what we are doing carefully, the reasoning behind that should make sense. The user is not going to have a copy of the image on their hard drive, so when they get the email it will have to have a source for the image. So, point them out to your public web server. There is another way to do this, which is less taxing on your web server - and that is to attach the image to the email. Here is how you do that:

'these two lines of code will replace 
'what was done above with the image.


'attach the image to the email and 
'give it a name for use later on
objCDO.AttachURL  "c:\images\net216.gif", "net216.gif"


'...
'inside the bodyHTML variable
bodyHTML = "<html>etc, etc..." & _
"<img src=""net216.gif""><br><br>"


'notice how the name you assigned above 
'is referenced as the image source?

Once you have all your HTML code squared away, set objCDO.body equal to your variable (bodyHTML) and send away! Move on to the next page to read about using the data we stored in the registration database last month.

Using the Registration Database

Chris Assenza

November 13, 2000

Now I have it, what do I do with it?

Good question actually, once you have collected user data from a form and stored it in a database, what do you do with that data? One thing you can do is allow access to special portions of your site. For instance, say a user registered as "brainman" with the password "flobe" and you wanted to give this user (and all others) access to your subscription content. The answer is, as usual, really very easy - in fact, if you have been following this series along, you have already done it, just for different reasons!

The answer involves a simple form, some ASP validation and processing (with SQL) and a redirect! Let's take a look at the form:

<html>
<head><title>Login Page</title></head>
<body>
<form name="logon" action="logon.asp">
Username: <input type="text" name="username">
Password: <input type="text" name="password">
<input type="hidden" name="isSubmitted" value="yes">
<input type="submit" value="Login">
</form>
</body>
</html>

You cannot get much easier then that, right? This form asks for a username, password and has a submit button. The form is using the post method so we will use "request.form" in our ASP code and the action is pointing to itself (pretend the page is named "login.asp"). If you have not understood so far, now is the time to pick it up - with computer stuff, repetition is the key to expertise in any particular area. Now, let's move on to the ASP code, which should also be old hat to you by now!

<%
if request.form("isSubmitted") = "yes" then
username = request.form("username")
password = request.form("password")


dim conn, strSQL, rst
set conn = Server.CreateObject("ADODB.Connection")
conn.ConnectionString = "dsn=wdvl_test"
conn.Open
set rst = Server.CreateObject("ADODB.Recordset")


strSQL = "SELECT * FROM tbl_Users;"
rst.Open strSQL, conn, 3, 3


found = 0
while not rst.EOF
if ((username = rst("Username")) AND 
	(password = rst("Password"))) then
found = 1
end if
wend


if found = 1 then
response.redirect 'subscription_zone.html'
else
ErrorMsg = "Username or password incorrect, please try again."
end if
end if
%>
<html>
<head><title>Login Page</title></head>
<body>
<% if ErrorMsg <> "" then %>
<font color="red" size="+2">
<b><%= ErrorMsg %></b>
</font>
<% end if %>
<form name="logon" method="post" action="logon.asp">
Username: <input type="text" name="username">
Password: <input type="text" name="password">
<input type="hidden" name="isSubmitted" value="yes">
<input type="submit" value="Login">
</form>
</body>
</html>

Note: The line "if ((username = rst("Username")) AND (password = rst("Password"))) then" is split at the word AND for display purposes, but in actual use it should be one line.

Rather then going through that code line-by-line, I will simply explain the concepts because you should recognize this code by now. First, the ASP checks the value of the isSubmitted form-field. If it is equal to "yes" the page proceeds to do some processing. After assigning the fields to variables, the next step is to establish a connection to the backend database. The SQL statement selects all the records from the tbl_Users table and makes them available as a recordset called "rst." Next, it is necessary to compare the values submitted on the page and the values in the recordset. We do this using a while loop that iterates through the recordset until it hits the end of the file. Each time, the if ((username = rst("Username")) AND (password = rst("Password"))) then statement asks if username (the variable) is equal to the current username in the recordset and asks if the passwords match. If a match is found, then the found variable is given a value of one, otherwise it stays equal to zero. Following the while loop, the next block of code checks to see what value found ended with. If it was a one, then response.redirect 'subscription_zone.html' sends the user to another page (whatever is defined in the single quotes). If found still equals zero, an ErrorMsg is stored and displayed when the form is redisplayed. On the next page, we will take a look at another use of the registration database - sending bulk email to your subscribers.

Sending Mass Emails to Subscribers

Chris Assenza

November 13, 2000

Another potential use for your registration database ties together just about everything discussed in this series of articles. This time, let's assume that you have a big database full of registrants, and you need to contact each and everyone of them to update them about a change to your service offerings. The best way, is of course, email, but how will you send it to all of them without setting up a mailing list and bulk email program? Easy, use a combination of form handling, CDONTS and SQL to get the job done.

For this particular exercise, I am not going to give you all the code, just snippets to help you on your way, you need to work on it and set it up yourself. We will begin by taking a closer look at the conceptual design.

First, you will need a simple web page that has a number of form fields on it. One should be a "From" field to say who the message is from. A second should be the subject of the email. For a third field, consider an option for sending HTML or plain text. Finally, the fourth field should be the body of the message.

Next, you need to develop a system that checks if the form is submitted and then processes that form appropriately. You will need it to A) Create the email message B) Obtain the email addresses for all your registered users, and C) Send an email to each user.

Now, part "A" should be simple, assign the value of the body field to bodyHTML or some other variable (I use msgBody below). Then, when the time comes, set objCDO.body = bodyHTML. But how about getting the email addresses out of the system and sending the mail? When sending a bulk message you need to start thinking about your server's capacity and the most efficient way to do things, because sending out a few hundred to thousand emails is pretty taxing. I recommend something like the following:

<%
'assume variables are declared and assigned 
'values up here, among other things.


strSQL = "SELECT First_Name, Last_Name, Email FROM tbl_Users;"
rst.Open strSQL, conn,3,3
while not rst.EOF
 msgBody = ""
Set objCDO = Server.CreateObject("CDONTS.NewMail")
objCDO.From = "Administrator@Somedomain.com"
objCDO.To = rst("Email")
objCDO.Subject = subj
'subj is the variable for the form field


msgBody = "Dear " & rst("First_Name") & " "
msgBody = msgBody & rst("Last_Name") & ": "

msgBody = msgBody & bodytext & vbCrLf
'bodytext is the variable for the form field


objCDO.Body = msgBody
objCDO.Send
set objCDO = nothing
rst.MoveNext
wend
%>

Again, nothing too complex that cannot be understood with a little effort. Presuming all the preprocessing is done, like assigning variables and validation, the first thing one needs to do is establish a connection to the backend database. The SQL statement used above retrieves the first name, last name and email address of every user in the tbl_Users table. The next section of code is the standard while not rst.EOF or end-of-file technique. Each iteration (or time through) the loop, the server will invoke a new mail object, configure the email attributes and send the email.

msgBody = "Dear " & rst("First_Name") & " " & rst("Last_Name") & ": " might be a bit confusing, so let's take a look at it more carefully. All that is really happening is that the first line of the msgBody is being set equal to "Dear So and So: ". We do this by concatenating (sticking together) the first name, a space, last name, and a colon, using the ampersand: &. The same sort of thing occurs on the next line. msgBody is set equal to itself to carry over changes from the previous line and bodytext is added to it. Assume bodytext is the variable you set equal to request.form("email_body"). Finally, the message is sent and the object set to nothing to free up resources and be less taxing on the server as it sends out many emails. The whole process repeats until the end of the recordset!

One thing I did not mention was how to deal with the "Send HTML or Plain Text" type form field. I am not going to show you line-by-line, but I will give you a terribly obvious hint. In the while loop, add some conditional processing (if statement) to check what the value of that form field is. If it is HTML, write some code that sets the mail and body formats equal to 0, if not, set them to 1. Easy as pie!

Conclusion

Hopefully some of you out there have learned what you wanted to learn with this series. We have discussed using ASP for form handling, validation, sending email, and working with simple databases. Using any of these techniques in conjunction with another can solve many problems the average web developer will encounter and can, in fact, be fun to work with. Next month I will be talking about something new, but I have not decided on any one topic. If there is something you are aching to know how to do but have not been able to figure it out, drop me an email and I will consider it for my next article! See you next month!