This time, instead of creating an HTML template, you'll create a custom Web-Item, so you'll become familiar with the difference between the two. Right-click the Custom WebItems entry in the WebClass Designer window and select Add Custom WebItem from the pop-up menu. Rename the new item Register, then right-click it again and select View Code.
The WebClass will create a new subroutine stub called Register_Respond. The WebClass calls the respond event on a WebItem when you set the WebClass Next-Item property to that item.
You'll need to add a Registration button to the Signon template so users can reach your registration screen. To modify the Signon template, right-click the Signon WebItem and select Edit HTML Template. VB will launch your default HTML editor.
Tip
To modify the editor that VB uses for editing HTML, click Tools Options, then click the Advanced tab. Enter the path to the editor you want to use in the External HTML Editor field, then click OK.
Change the last row in the table so it contains two buttons instead of one:
Notice that the name of both buttons is Submit. That way, you can easily add a check in the Signon_frmSignon event code to determine which button the user clicked. If the user is trying to register, you can reroute them to the Registration screen. Add the following code immediately after the line action = Request .Form("Submit") in the Signon_frmSignon event code.
If action = "Register" Then
Set NextItem = Register
Exit Sub
End if
When the code executes, setting the NextItem property to Register fires the Register_Respond event for the Register custom WebItem. In the Register_ Respond event, you'll return the HTML to show the Registration screen. Listing 5.2 shows the HTML for the Registration screen. Place this code in the Register_ Respond event stub.
Listing 5.2: HTML for Registration Screen (in Signon.dsr)
Private Sub Register_Respond()
Dim s As String
Dim sBody As String
s = getHTMLTemplate()
s = Replace(s, "<!—Title—>", "SecuredSite Registration")
You cannot run the WebClass successfully until you add the getHTMLTemplate function. You'll see that within a few paragraphs.
Because we're not asking for much information in this application, there's little difference between the HTML for the Signon and the Registration screens. Normally, you would also ask for other information during registration, such as e_mail addresses, telephone numbers, street addresses, titles, etc. In any event, the important thing to notice here is that you can use WebClasses to manage the presentation layer or to generate it. Which one is best for you depends on your work situation and the needs of the program.
The Register_Respond event does contain some useful code. First, you'll eventually get tired of writing the standard HTML tags. That's why HTML editors invariably provide a template. The line s=getHTMLTemplate() shows you how easy this is to do in code. The getHTMLTemplate function returns an HTML string containing some replaceable markers for the title and body of the document. The markers are formatted as HTML comments, so (except for the title) they won't be visible in the browser if you don't replace them with valid HTML.
Private Function getHTMLTemplate() As String
getHTMLTemplate = "<html><head><title>" & _
"<!—Title—></title></head><body>" & _
"<!—Body—></body></html>"
End Function
The rest of the Register_Respond routine sets up the HTML to display the screen. Finally, the routine uses the replace function to insert the title and body of the document in place of the markers.
In the Signon HTML Template, you hard-coded the URL for the form submission. In this routine, you let the WebClass dynamically create the URL by using the URLFor function. The URLFor function takes one or two parameters—a WebItem object (or a string containing the name of a WebItem) and, optionally, the name of a method for the WebItem. The function returns a URL referencing the specified WebItem or method.
The advantage of using URLFor is that you can change the URL based on factors unknown at design time. For example, suppose you have administrative users and non-administrative users, who have different privilege levels. If you use hard-coded URLs in HTML templates, you need to have more than one template. If you use dynamic URLs, you make a decision at runtime to display the appropriate URL based on the user's privilege level. If you want to see what the WebClass inserts into the HTML string, right-click the Registration page at runtime and select View Source from the pop-up menu.
When the user clicks the Submit button, you need to validate the registration information and store it in the registration file. You need to create another custom event. Right-click the Register WebItem in the WebClass Designer window and select Add Custom Event. Name the event Register so it will match the name in the URLFor function call.
Listing 5.3 contains the Register_Register event code.
Listing 5.3: SecuredSite Registration Event Code (in Signon.dsr)
The code in the Register_Register event will not execute successfully until you add the code from the remainder of this section.
The first part of this routine only validates the information entered. After you're sure that you have valid information, the routine tries to find the sign-on. For this program, finding the sign-on is a two-part process. First, the findSignon function calls a function called readTextFile:
s = readTextFile(App.Path & "\registration.txt")
You'll see the code for the readTextFile function shortly, but I want to introduce two new objects first. The readTextFile function uses the Scripting.File-SystemObject to open and read the text file. It returns a string containing the textfile contents. The FileSystemObject is part of the Microsoft Scripting Runtime Library installed with both ASP and Visual Basic 6. It can check for the existence of files and can copy or move files. The FileSystemObject by itself cannot read files, but it provides an OpenTextFile method, which returns a TextStream object that can read and write text files. The VB documentation explains how to use the FileSystemObject and the TextStream object in detail, but basically, you provide a filename, a constant describing the action you want to take (ForReading, ForWriting, or ForAppending), and optionally, a Format constant that sets the Text-Stream object to use either ASCII or Unicode. The Format constants are Tri- StateTrue, TriStateFalse, TriStateMixed, and TriStateUseDefault. Of course, you don't have to use the FileSystemObject—you could use standard VB file access methods instead.
Add the readTextFile function to the Signon WebClass.
Private Function readTextFile(aFilename As String) As String
Remember, we decided to store the sign-ons and passwords as comma-delimited items, one per line. The findSignon routine splits the string returned from the readTextFile function into an array, then iterates through the array, splitting each line item into a two-item array at the comma.
Add the findSignon function to the Signon WebClass.
Private Function findSignon(aSignon, Optional retInfo _
As Variant) As Boolean
Dim vArr As Variant
Dim lRegCount As Long
Dim i As Integer
Dim arrSignonInfo As Variant
Dim s As String
On Error GoTo Err_FindSignon
s = readTextFile(App.Path & "\registration.txt")
If Len(s) > 0 Then
s = Left$(s, Len(s) - 2)
vArr = Split(s, vbCrLf)
lRegCount = UBound(vArr)
For i = 0 To lRegCount
arrSignonInfo = Split(vArr(i), ",")
If StrComp(aSignon, arrSignonInfo(0), _
vbTextCompare) = 0 Then
findSignon = True
If Not IsMissing(retInfo) Then
retInfo = vArr(i)
End If
Exit Function
End If
Next
End If
Exit_FindSignon:
Exit Function
Err_FindSignon:
Err.Raise Err.Number, Err.Source, Err.Description
Resume Exit_FindSignon
End Function
If the routine finds a matching sign-on, it returns True. If you include the optional retInfo parameter, the findSignon routine sets it to the matching item.
The Register_Register routine checks the return value from findSignon to see whether any other user has already selected the requested sign-on. If so, it asks the user to select a different sign-on; if not, it appends the sign-on and password to the registration file and displays a Congratulations message containing a link back to the Signon screen. After registration, the user should be able to sign on successfully.
The Register_Register routine calls an appendToTextFile method to append the new sign-on and password. Again, the code uses the Scripting.FileSystem-Object and TextStream objects to write to the registration.txt file. Add the code for the appendToTextFile method to the Signon WebClass.
Private Sub appendToTextFile(aFilename As String, _
value As Variant)
Dim fs As FileSystemObject
Dim ts As TextStream
Dim v As Variant
Dim i As Long
Dim itemCount As Long
On Error GoTo Err_appendToTextFile
' open the text file in Append mode
Set fs = New FileSystemObject
Set ts = fs.OpenTextFile(aFilename, ForAppending, _
True, TristateUseDefault)
If (VarType(value) And vbArray) = vbArray Then
itemCount = UBound(value)
For Each v In value
ts.WriteLine v
Next
Else
ts.WriteLine value
End If
ts.Close
Set ts = Nothing
Set fs = Nothing
Exit_appendToTextFile:
Exit Sub
Err_appendToTextFile:
App.LogEvent "Unable to append to the file: " & _
aFilename & " in the appendtoTextFile routine."
Err.Raise Err.Number, "appendToTextFile", _
Err.Description
Resume Exit_appendToTextFile
End Sub
You need to add another Custom WebItem to display the Congratulations message. Right-click the Custom WebItems entry in the WebClass Designer and select Add Custom WebItem. Rename the new WebItem Congratulations. Double-click the Congratulations WebItem and replace the empty Congratulations_ Respond event code with the following code:
Private Sub Congratulations_Respond()
Dim s As String
Dim sBody As String
s = getHTMLTemplate()
s = Replace(s, "<!—Title—>", "Congratulations")
sBody = "You have successfully registered. Click <a href=""" _ & URLFor(Signon) & """ target=""_top"">here</a> to continue."
s = Replace(s, "<!—Body—>", sBody)
Response.Write s
End Sub
You're almost done. You have all the routines needed for the sign-on; now you just need to call them from the Signon_frmSignon method. Here's the completed code for the Signon_frmSignon method:
Private Sub Signon_frmSignon()
Dim aSignon As String
Dim aPassword As String
Dim action As String
Dim tmpSignon As String
Dim tmpPassword As String
Dim arrSignonInfo As Variant
Dim v As Variant
action = Request.Form("Submit")
If action = "Register" Then
Set NextItem = Register
Exit Sub
End If
Session("LastSignon") = ""
Session("LastPassword") = ""
aSignon = Request.Form("Signon")
aPassword = Request.Form("Password")
If Trim(aSignon) = vbNullString Then
Session("msg") = "You must enter a signon."
Set NextItem = Signon
Exit Sub
End If
Session("LastSignon") = aSignon
If aPassword = vbNullString Then
Session("msg") = "You must enter a password."
Set NextItem = Signon
Exit Sub
End If
Session("LastPassword") = aPassword
If findSignon(aSignon, arrSignonInfo) Then
arrSignonInfo = Split(arrSignonInfo, ",")
If StrComp(aPassword, arrSignonInfo(1), _
vbTextCompare) = 0 Then
Session("Signon") = aSignon
Session("Password") = aPassword
With Response
.Write "Finished checking password" _
& "/signon." & "<BR>"
.Write "Signon=" & aSignon & "<BR>"
.Write "Password=" & aPassword & "<BR>"
End With
Else
Session("msg") = "Invalid Password"
Set NextItem = Signon
End If
Else
Session("msg") = "Unrecognized Signon. " _
& "Try again or click the Register button " _
& "to register."
Set NextItem = Signon
End If
End Sub
You should now be able to run the project. When you register successfully, you should see the Congratulations message in your browser. In the next section, you'll see how to use the sign-on and password WebClass to force users to sign on before viewing any content pages in your application.