Special Edition Using Microsoft® Visual Studio for Enterprise Development

Previous chapterNext chapterContents


- 17 -
Server-Side Programming in an I-net Environment

by Robert S. Black

Learn how to decide what language you should use based on various factors, including leveraging existing resources and what platform the software will run.
Consider what software you should use to connect to the server, such as CGI, WinCGI, ISAPI, NSAPI, and Active Server Pages, and their relative strengths and weakness.
Learn to quickly create a dynamic web site by scripting with Visual InterDev.
Follow a demonstration of the use of WinCGI, Active Server Pages, Visual Basic, style sheets, and HTML.
Learn how to connect to the database by using Active Server Pages and Visual Basic.
Follow an actual three-tier connection example.

The need for data fuels the prevalence of information systems in the workplace and the Internet for everyone to use. Servers are required to parcel out data efficiently to handle the many requests. Programming for the server takes a great deal of care. Many issues--such as security, speed, and future functionality--weigh heavily in what software to use and how to implement the best server for internal I-net use (an intranet) and external I-net use (the Internet).

When picking the correct way to implement a server, many considerations should be taken into account. What's the purpose? Are you boxing yourself into future problems? Can you get the information to those who need it quickly and efficiently? Is access to the data restricted sufficiently so that unauthorized users can't view or edit the data? This chapter deals with these issues, as well as looks at what processing should take place on the server. What languages, software, and protocols should be used? How should different components be integrated? This chapter is designed as an overview to look at the big picture in server-side programming. Many of the other chapters provide a greater in-depth knowledge of particular areas, such as Chapter 10, "Clients, Servers, and Components: Web-Based Applications"; Chapter 14, "Developing Active Content with Visual InterDev"; Chapter 15, "Advanced Visual InterDev Concepts"; and Chapter 16, "Visual InterDev Design-Time Controls." n

Deciding on a Language

Deciding what language in which to write your system is a function of your requirements and design. More specifically, scalability, portability, time to produce, the use of current resources, and whether this language can carry out certain functions should be paramount in deciding what language or languages to use.

Keep in mind that it doesn't matter to the client what languages are used on the server. If the client is using the Netscape Navigator browser, it will work fine with all Microsoft software on the server. The only time the client is affected is with the scripting language or components on the client.

Because deciding what language to use depends on a given situation, it's difficult to give explicit rules governing language selection. Therefore, this area will be covered briefly here, but the remaining sections of this chapter discuss factors that influence language decisions.

You need to take current resources into consideration when designing a system. Whether it's with existing software or personnel, the correct design should take these factors into account:


NOTE: More software than database objects can be reused for I-net purposes. Database objects are ideal for reuse because of the features mentioned. Other software, such as data-processing components, also could be reused. This software could be called from a web page instead of traditional client software. Other objects share in the benefit that existing code can continue to be used.


CAUTION: Keep in mind that client browsers, even though they might support the common mechanisms, are no longer identical in their functionality. Over the years, Internet Explorer and Navigator have diverged from each other in critical areas such as support for Dynamic HTML and the version of the Java SDK being supported. However, the web browser still presents the closest thing we have today to a client-independent computing environment.

Deciding How to Connect to the Server

When a user request is made to a server, the server attempts to handle the request. If the request is for a static HTML document, the server software returns the document at the location the user requested. If you want to do processing on that request, many decisions need to be made, such as how you connect to the server and what software you use to do the processing.

Deciding how to connect to the server can be one of the biggest decisions in creating a successful I-net project. Ignoring certain needs could cause tremendous problems for the future of your project. Some key trade-offs to consider in the design of a system are performance, portability, scalability, leveraging existing resources, and security.

It's important to recognize that there's no one solution for every problem. You should weigh heavily all the trade-offs and design a system that works best for your situation and that minimizes your risk.

Possible choices on how to connect to the server include using the Common Gateway Interface (CGI) or Windows Common Gateway Interface (WinCGI), using proprietary application program interface (API) calls, or using proprietary software to connect. Each choice has distinct advantages and disadvantages. With each choice are more decisions to make, such as which API or proprietary software should you use. The following three sections discuss connections with CGI, WinCGI, proprietary APIs, and web application development tools.

Connecting to the Server with Common Gateway Interface

CGI is a standard for the interface between external programs and web servers. In a nutshell, CGI is a specification that allows external programs to communicate and respond to queries from web clients through the web server. When a client makes a request to a web server for a CGI program execution, the web server executes the CGI program and passes the execution parameters it received from the client to the CGI program. The request and the accompanying parameters are sent as an HTTP request. The CGI program parses the parameter list, executes the program, compiles the results, and sends them back to the client through the web server.

Advantages and Disadvantages of CGI

As with any connection method, CGI has its advantages and its disadvantages. Using CGI has numerous advantages:

The two key disadvantages of CGI are its performance and security problems:

CGI Solutions

Some solutions to deal with CGI's problems include using proprietary APIs, special development tools, or a site monitoring and performance tool. Coverage of proprietary APIs and special development tools are presented later in the sections "Connecting to the Server with Proprietary APIs" and "Connecting to the Server with Web Application Development Tools."

Programming with CGI

Although writing a primitive CGI program is simple, writing usable software that has all the necessary functionality and meets the security needs of a system isn't.


ON THE WEB:You can find a wealth of information to explain and demonstrate how to implement CGI in various languages. Two sites with links to CGI information are http://www.progsource.com/cgi.html and http://www.Stars.com/Software/CGI.

You can develop CGI programs in Visual C++ or Visual Basic. To develop CGI programs in Visual Basic, you must use the WinCGI programming interface provided by Microsoft at its web site. WinCGI is a mechanism that uses INI files to replicate the stdin functionality used by the CGI standard to pass parameters to the program.


NOTE: Some web servers don't support WinCGI.

When a request is made to a CGI program, the web server passes a filename as a command-line argument. The CGI program takes data from this file to determine what information was requested and where the output should be sent, among other data. This temporary file is generated for each CGI request. The CGI program then makes necessary computations and returns the appropriate data. The WinCGI class in Listing 17.1 demonstrates retrieving INI entries from a profile file to be used by the CGI program.

Listing 17.1  A Generic WinCGI Class

Option Explicit
Private Const MAX_BUFFER_SIZE = 4096
Private m_sRequestMethod As String
Private m_sOutputFileName As String
Private m_iOutputFileNumber As Integer
Private m_sProfileFile As String
Private m_sQueryString As String
Private m_colArguments As New Collection
`Win32 API call to get data from a file that is in an INI format
Private Declare Function GetPrivateProfileStringA Lib "kernel32" _
   (ByVal lpApplicationName As String, ByVal lpKeyName As Any, _
    ByVal lpDefault As String, ByVal lpReturnedString As String, _
    ByVal nSize As Long, ByVal lpFileName As String) As Long
`Does the initialization of the object
Public Function Initialize() As Long
On Error GoTo Handle_Error
    Set m_colArguments = GetArguments
    m_sProfileFile = m_colArguments(1)
`Gets the data sent, request method and file which to write the results
    m_sQueryString = GetProfile("CGI", "Query String")
    m_sRequestMethod = GetProfile("CGI", "Request Method")
    m_sOutputFileName = GetProfile("System", "Output File")
`Gets the next available filenumber for output
    m_iOutputFileNumber = FreeFile
    Open m_sOutputFileName For Append As #m_iOutputFileNumber
Handle_Error:
    Initialize = Err
End Function
`Gets data from the profile file
Private Function GetProfile(ByVal sSection As String, ByVal sKey As String) As String
    On Error GoTo Handle_Error
    Dim lResult As Long
    Dim sBuffer As String * MAX_BUFFER_SIZE
    lResult = GetPrivateProfileStringA(sSection, sKey, "", _
                sBuffer, MAX_BUFFER_SIZE, m_sProfileFile)
    If lResult = 0 Then
        GetProfile = ""
    Else
        GetProfile = Left$(sBuffer, lResult)
    End If
    Exit Function
Handle_Error:
    GetProfile = ""
End Function
`Returns a collection of Command line arguments
`The first one is the filename of the Profile file
Private Function GetArguments() As Collection
    Dim sCommand As String
    Dim colTemp As New Collection
    Const SPACE = " "
    Dim s As String
    Dim x As Long
    sCommand = Trim$(Command)
    x = 1
    While sCommand <> "" And x <> 0
        x = InStr(sCommand, SPACE)
        If x <> 0 Then
            s = Left(sCommand, x)
        Else
            s = sCommand
        End If
        sCommand = Trim$(Right(sCommand, Len(sCommand) - x))
        colTemp.Add s
    Wend
    Set GetArguments = colTemp
    Set colTemp = Nothing
End Function
Public Sub Send(ByVal s As String)
    Print #m_iOutputFileNumber, s
End Sub
`Terminates the class
Private Sub Class_Terminate()
Set m_colArguments = Nothing
Close #m_iOutputFileNumber
End Sub
`Returns the data sent to the CGI program
Public Property Get QueryString() As String
QueryString = m_sQueryString
End Property
`Returns the request method such as GET or POST
Public Property Get RequestMethod() As String
RequestMethod = m_sRequestMethod
End Property

To use the class in Listing 17.1, save it with the class name of CCGI. For an example of how to use this class, Listing 17.2 is a program that returns a web page containing the favorite color submitted by the user.

Listing 17.2  The Favorite Color WinCGI

Sub Main()
Dim oCGI As New CCGI
Dim sQuery As String
On Error GoTo CheckError
`Initialize the CGI object
oCGI.Initialize
`Get the query string
sQuery = Trim$(oCGI.QueryString)
`Parse the query string to get the color
sQuery = Mid(sQuery, InStr(sQuery, "=") + 1)
oCGI.Send ("")
Select Case UCase$(oCGI.RequestMethod)
    Case "GET"
        Select Case sQuery
            Case "Red"
                oCGI.Send ("My favorite color is Red.")
            Case "Blue"
                oCGI.Send ("My favorite color is Blue.")
            Case "Yellow"
                oCGI.Send ("My favorite color is Yellow.")
            Case Else
                oCGI.Send ("I don't have a favorite color.")
        End Select
    Case Else
        oCGI.Send ("Unable to complete request.")
End Select
Set oCGI = Nothing
Exit Sub
CheckError:
oCGI.Send ("")
oCGI.Send ("Error main " & Err & ": " & Err.Description)
End Sub

To use the code in Listing 17.2, place it in the same project as the class in Listing 17.1, compile it as cgitext.exe, and put it in the cgi-win directory of your web server. Run your web server and make calls to the program with the HTML in Listing 17.3 in a web page.

Listing 17.3  Favorite Color HTML


<FORM ACTION="http://localhost/cgi-win/cgitest.exe" method="GET">
<table width=600>
<tr><td align=center valign=top><input type=submit name="cmdSubmit"
    value="Blue"></td></tr>
<tr><td align=center valign=top><input type=submit name="cmdSubmit"
    value="Red"></td></tr>
<tr><td align=center valign=top><input type=submit name="cmdSubmit"
    value="Yellow"></td></tr>
<tr><td align=center valign=top><input type=submit name="cmdSubmit"
    value="None"></td></tr>
</table>
</form>

Connecting to the Server with Proprietary APIs

Other solutions to the security and performance problems of CGI come in the form of proprietary APIs. This type of API also adds functionality to server connections, but introduces new problems.

Specifically, this section refers mainly to Microsoft's Internet Server Application Program Interface (ISAPI) and Netscape Communication Corporation's Netscape Server Application Program Interface (NSAPI). ISAPI is supported by Microsoft's full line of web server products, including Internet Information Server (IIS). NSAPI is supported by all Netscape web servers (Communications, Commerce, FastTrack, and Enterprise), as well as versions 2.0 and 2.5 of Netscape Proxy Server.

Advantages and Disadvantages of Proprietary APIs

Proprietary APIs vary from CGI in many ways. These differences lead to some key advantages and disadvantages of using proprietary APIs over CGI.

Programming with ISAPI and NSAPI has distinct advantages, the biggest being the speed and fewer resources required. Because these APIs spawn new threads instead of new processes, the server has significantly less load. The time it takes to generate a new thread instead of a new process is greatly reduced, so users will have a much greater response time when using this system.

ISAPI and NSAPI also can further break down Hypertext Transfer Protocol (HTTP) so that more functionality can be achieved with security validation.

One obvious disadvantage of proprietary APIs is their proprietary nature. If you decide to switch servers entirely, new software needs to be written.

Another less obvious but potential problem is the increased complexity of programming. Multithreaded applications, by nature, are more difficult to design and harder to debug than single-threaded applications. Also, developers have to deal with cleaning up data in memory.

ISAPI and NSAPI also have a greater potential in crashing a web server. Because they use in-process DLLs, a mistake in the code could bring down the entire server instead of a single process.

ISAPI Versus NSAPI

ISAPI and NSAPI are two competing APIs developed by Microsoft and Netscape, respectively. Both APIs are designed to accomplish essentially the same task--that is, to allow developers to write applications that can run on a web server. As competing APIs, they accomplish this task in different ways and are obviously incompatible with each other. As is always the case in such scenarios, the individual APIs work best with the development tools and products from the respective vendor. However, you must consider some issues when making a decision about which API to use.

ISAPI is a Microsoft standard that works with Microsoft server products and the Visual Studio development tools. However, it's a Windows NT-only solution that can't be ported to UNIX or other platforms. NSAPI, on the other hand, works best with Netscape server products and is available on a multitude of platforms, including various flavors of UNIX and Windows NT. ISAPI's strong integration with Microsoft tools gives it a distinct advantage on the Windows NT platform and, if you're developing for a Windows-only environment, probably makes it a more flexible and robust choice.

NSAPI can be written in C and C++, whereas ISAPI can be written in C, C++, and Pascal. As an API, NSAPI can be used with Visual C++. However, most notable from a Visual Studio perspective is Visual C++'s ready support of ISAPI application development through the use of a supplied wizard. The wizard makes it very easy to get started with building an ISAPI application and provides the initial framework necessary to develop more complex applications.

Connecting to the Server with Web Application Development Tools

Connectivity between the client and server can be more easily developed with special web application development tools. These tools typically provide a connection between the client and the server, and an easy manner to connect to a database.

Web application development tools include Netscape's LiveWire (http://www.netscape.com), Allaire's Cold Fusion (http://www.allaire.com), NetDynamics (http://www.netdynamics.com), and Microsoft's Visual InterDev (http://www.microsoft.com). All these development tools allow for special scripts to be used to develop the interactivity between the client and the web server, and the web server and the database. You can use scripting as the glue to hold together various components to complete tasks necessary for a web site. The following sections cover Visual InterDev in more depth because it's part of the Visual Studio suite of tools.

Advantages and Disadvantages of Web Application Development Tools

Like with connecting with any other method, this approach has advantages and disadvantages. Using web application development tools has several advantages over developing all the code yourself. The speed at which you can develop software is greatly increased. You can maintain a consistent look and feel for your entire web site. You can manage overall control of your web site, such as the order in which pages are presented to users.

Some disadvantages of web application development tools include the following:

Alternative Development Tools

This section explains what languages and servers each development tool uses; the next section provides detailed coverage of actual implementation with Microsoft Visual Studio's Visual InterDev.

Netscape's LiveWire uses a modified JavaScript as its scripting language. Additional functions are added to JavaScript to make it more useful on the server. For example, several URL manipulation functions wouldn't be required on the client. LiveWire can run on UNIX, Windows NT, and Macintosh, and the scripts can run on any Netscape server.

Allaire's Cold Fusion uses its own scripting language, the Cold Fusion Markup Language (CFML). The software can run on Windows NT and Windows 95 and can use Microsoft IIS and Netscape Enterprise Server.

NetDynamics, Inc.'s NetDynamics 3.1 uses Java instead of a scripting language. This means that you can write software for it by using Microsoft's J++, Symantec's Visual Café, or JavaSoft Java Development Kit (which comes with NetDynamics). NetDynamics runs on Windows NT, Windows 95, and various UNIX machines. NetDynamics can use any CGI web server, any NSAPI 2.0-enabled web server, or an ISAPI-enabled web server.


For more information in developing with Java, see Chapter 7, "Creating Components with Visual J++."

Visual InterDev is part of Microsoft's Visual Studio suite. The scripts run as Active Server Pages (ASP) and will run on Microsoft IIS. Developers can use JScript or VBScript. The following section demonstrates the use of server-side scripting with Visual InterDev.

Using Server-Side Scripting with Visual InterDev

Scripting with Visual InterDev provides users with an easy way to quickly create a dynamic web site. You can use scripting to link separate components as well as make calls to the database.


For a more complete look at Visual InterDev, see Chapter 14, "Developing Active Content with Visual InterDev," Chapter 15, "Advanced Visual InterDev Concepts," and Chapter 16, "Visual InterDev Design-Time Controls."

VBScript or JScript?

JScript, Microsoft's implementation of JavaScript, and VBScript, Microsoft's scripting language, are the two scripting languages featured in Visual InterDev. VBScript and JScript will run as Active Server Pages on a server with Internet Information Server. They both can makes calls to OLE objects. And with the key exception that VBScript has error trapping whereas JScript doesn't, they both have similar functionality. (See "Connecting to the Database" later in this chapter for more information on error trapping.)

Because VBScript and JScript have similar functionality, deciding whether to use VBScript or JScript on the server depends mainly on personal preference. If the project developers know Visual Basic, VBScript would be an ideal choice because it's a subset of VB. If developers are using JScript on the client side, JScript on the server makes sense so that developers have to use only one scripting language and can become familiar with it.

Both scripting languages have similar functionality, so a decision can be made from a personal point of view rather than a technical one. Portability isn't an issue because I'm talking about only server-side scripting here.

Visual InterDev ActiveX Objects

Objects native to Visual InterDev are used on the server and can be called with JScript or VBScript. These objects allow developers to easily access the database, access information on the server, and provide protocols to interface with the client. The following sections deal with some of these objects. A more thorough handling of this material is provided with the Visual InterDev documentation, but these sections will help highlight and give a good overall understanding of the material.

Rather than create special functions in VBScript or JScript, Microsoft includes various classes in Visual InterDev and allows developers to call these classes from either scripting language.

Two of these classes, Server and Application, contain methods to perform miscellaneous functions that make programming on the server easier. The Server class, in addition to having HTML and URL manipulation as well as other functions, has a CreateObject method. CreateObject creates an instance of one of several objects:

The Application class can set variables of all users of a particular application. This class deals with windowing (size, state, which one is active). It has events that allow developers to write code for when an event occurs, such as the BeforeApplicationShutDown event, which saves information before the application is shut down.

Interface Between the Client and Server  Visual InterDev uses two ActiveX objects to interface between the client and the server. The Request and the Response objects enable interaction between the client and server. The Request object gives developers access to all the information passed with an HTTP request. This information includes items from a form, query parameters, client certificates, and cookies passed from a client browser. The following requests a cookie named ExampleCookie from the client and returns a collection:

<%= Request.Cookies("ExampleCookie") %>

The Response object allows developers to pass information to the client browser. There are various properties and methods--for example, Expires and Write, which set how many minutes the web page has to be refreshed when it's requested and which can dynamically write HTML scripts to the client, respectively.

To set the ExampleCookie to the string "Hello World!", use the following code:

<% Response.Cookies("ExampleCookie") = "Hello World!" %>


TIP: Setting Response.Expires to zero minutes prevents web browsers from caching the web page. This can be useful for keeping track of the number of times a user accesses a particular web page on your web site or for changing the advertisement every time the page is requested.

Managing Client State  In many instances, keeping track of where a user is in your site is important. For example, if a user has to fill out a form before being presented with other information, you must make certain that the form is complete before the rest of the information is presented. To do so, you must keep track of the user's state. Storing information on the client computer can be done in the form of a cookie with the help of the Session object or by storing information directly on a web page. You can use the Session object to help administer a user session. The Session object includes the SessionID and Timeout properties. SessionID provides a unique identifier for a user and can repeat when the web server is restarted. Timeout is the number of minutes a session can remain idle before disconnecting the user.

The Session object has an explicit way in which to keep state. You can store information in the Session object as such:

<% Session("lastpage") = 37
   Session("username") = "adb" %>

This information is actually stored by using a cookie. These methods won't work with browsers where cookie support has been disabled by users.

Rather than trust cookies on the client machine to keep track of user state information, you could put that functionality directly on the client's web page. This way, your pages can work with browsers that don't support cookies. It also would ensure that users can't block the cookie from being received. It wouldn't prevent users from altering the SessionID sent, but you can take measures to reduce the risk to virtually zero. To do this, you can create a random string generator on the server that would supply each new logon with a SessionID value. Then store this value on the web page in the following manner, where the SessionID is in single quotes after value=:

<input type=hidden name='SessionID' value='A"Z@vqiAV7D.&od=q?Sg'>

This data is returned to the server much like a Submit button submits data to the server, but the control is hidden from users' visibility. Store the SessionID string in the database with other characteristics of the user session. As well as for managing a client's state, you can use the data stored in the database for keeping a history of user logons and expiring a user session. This gives you similar functionality to the Session object without relying on cookies.


NOTE: A user would have a hard time generating a string that matches another user's SessionID. If you generate a string 20 characters long with 80 possibilities per character, the chances of matching an existing string are one in 80 to the 20th power.

Connecting to the Database  Visual InterDev uses ActiveX Data Objects (ADO) to connect to a database from a scripting language. The main advantage of using ADO is convenience. For other ideas on connecting to a database, see "Using Server-Side Components" later in this chapter. One big problem with using scripting languages in Visual InterDev to connect to the database is the lack of error-handling capabilities. JScript has no error-handling functions, whereas VBScript has only On Error Resume Next. You shouldn't connect to the database without being able to trap errors due to the frequency in which errors are generated when interacting with a database.

On Error Resume Next tells the program to continue to the next line when an error is encountered. One way to handle errors is with the code in Listing 17.4.

Listing 17.4  Inline Error Handling

On Error Resume Next
... ` your own code
... ` your own code
`Line which may generate error
If Err <> 0 Then
   Msgbox "Error " & Err & " : " & Err.Description
   Err.Clear
End If
...

You need to make many determinations in connecting to the database, such as the database, the data source, and what type of connection you want to open. The code in Listing 17.5 helps you connect to the database, although building the connect string depends on the specifics for your system.

Listing 17.5  Connecting to the Database with ADO and VBScript

 `Create the database connection
Set adoDB = Server.CreateObject("ADODB.Connection")
`Open session with using the connect string
`adoDB_DBConnectString is stored in your projects inf file
`the connection string can include user name and password
aboDB.Open Session("adoDB_DBConnectString")
`Create the Command Object
Set cmdQuery = Server.CreateObject("ADODB.Command")
`Create the resultset
Set ars = Server.CreateObject("ADODB.Recordset")
`Set up the query
cmdQuery.CommandText = "SELECT * FROM ExampleTable "
cmdQuery.CommandType = 1
`set the active connection to the command object
Set cmdQuery.ActiveConnection = DBConn
`open the resultset
ars.Open cmdTemp, , 0, 1

The following code loops through a result set and sends the data to the web browser:

Do While Not ars.Eof
    Response.Write ars("ExampleColumn")
    ars.MoveNext
Loop


NOTE: If you want to use ADO-defined constants rather than hard-code the numbers in your code, include the location of the file that stores this information--ADOJAVAS for JScript and ADOVBS for VBScript:
<!--#include virtual="/ASPSAMP/SAMPLES/ADOVBS.INC"-->
An #include directive allows you to include an external file as part of your ASP page code. It's similar to the #include directive used in C/C++.

Using Server-Side Components

Using server-side components can be great for code reuse and portability of software. Even if you choose a proprietary solution instead of a more generic one, if you design your software with a component-based architecture, future modifications and additions to your system can be much easier and cost-effective. Also, if you're connecting to the database, you have much more error-handling capability than using scripting.


More information on using server-side components is available in Chapter 6, "Creating Components with Visual C++," Chapter 9, "Using ActiveX Components in a Client/Server Environment," and Chapter 10, "Clients, Servers, and Components: Web-Based Applications."

This section demonstrates an actual three-tier example. The modMain.bas is the main program that makes calls to the Billing.CLS or Billing2.CLS component, which in turn interfaces with the database.


NOTE: After changing the database, the code in the main program remains the same by simply calling Billing2.CLS. The interface for the second class doesn't change at all from the first--just the implementation changes. Changing the middle tier can prevent code changes in the interface and allows all applications that use the database to make calls to a single program.

The ACME Billing Company wants to provide a customer balance, the date the balance is due, and the address to which to send the balance. The company already has an ActiveX DLL that other software calls to generate a bill.


NOTE: This example is greatly simplified for demonstration purposes.

Tables 17.1 and 17.2 list the columns, their types, and descriptions for the Customer and Region MS-Access Database tables.

Table 17.1  Customer Database Table Structure

Column Name Type Explanation
ID AutoNumber Identity
LastName Text Customer's last name
FirstName Text Customer's first name
Balance Currency Customer's balance
EmailAddress Text Customer's unique email address
Region Number Foreign key to region

Table 17.2  Region Database Table Structure

Column Name Type Explanation
ID AutoNumber Identity
Name Text Region's name
Address1 Text 1st line of billing address
Address2 Currency 2nd line of billing address
Day Text Day of the month which the bill is due

Listing 17.6 is the Visual Basic code for an ActiveX DLL that returns the appropriate data to a calling program. This code uses a Microsoft Access database.

Listing 17.6  Billing Class Interface to the Database

Option Explicit
`Directory where the database is found
Const DBPath = "c:\Billing.mdb"
`Error Codes
Const NO_RECORD_FOUND = 1234
Const ILLEGAL_VALUE_NAME = 1235
`Connection to the database
Private m_DB As Database
`Given an identifier and the name of the data that you wish to retrieve
`GetValue will return an error code and set vValue to the value of the 
`data requested
Public Function GetValue(ByVal sIdentifier As String, ByVal sValueName As String, ByRef vValue As Variant) As Long
`String used to hold a SQL statement
Dim sQuery As String
`the returned recordset
Dim rs As Recordset
On Error GoTo CheckError
`set return value to successful
GetValue = 0
`Check the desired value name
`if it is valid then execute the appropriate SQL statement
`otherwise return an error code
Select Case sValueName
    Case "Balance"
        sQuery = "SELECT Balance FROM Customer WHERE EmailAddress = '" & sIdentifier & "` "
    Case "Day"
        sQuery = "SELECT Day FROM Region, Customer WHERE EmailAddress = '" & sIdentifier & _
                 "` AND Customer.Region = Region.ID "
    Case "Address1"
        sQuery = "SELECT Address1 FROM Region, Customer WHERE EmailAddress = '" & sIdentifier & _
                 "` AND Customer.Region = Region.ID "
    Case "Address2"
        sQuery = "SELECT Address2 FROM Region, Customer WHERE EmailAddress = '" & sIdentifier & _
                 "` AND Customer.Region = Region.ID "
    Case Else
        GetValue = ILLEGAL_VALUE_NAME
End Select
`if the value name is valid then continue
If GetValue = 0 Then
    `get the value
    Set rs = m_DB.OpenRecordset(sQuery, dbOpenSnapshot)
    If Not rs.EOF Then
        vValue = rs(0)
    Else
        GetValue = NO_RECORD_FOUND
    End If
End If
Exit Function
CheckError:
GetValue = Err
End Function
Private Sub Class_Initialize()
Set m_DB = OpenDatabase(DBPath)
End Sub
Private Sub Class_Terminate()
Set m_DB = Nothing
End Sub

To test this code, include it in a project with a module that has the code from Listing 17.7. Put an MDB (Access database) file with the above database structure (refer to Tables 17.1 and 17.2) in the same directory where your Visual Basic project files reside. Make certain that you have some entries in the database. The message box returns the error code and if successful the desired data. Set sEmail to a value in the database.

Listing 17.7  Main Program That Calls Billing.CLS

Sub Main()
Dim oBilling As New CBilling
Dim lCode As Long
Dim x As Variant
Dim sEmail As String
Dim sValueName As String
sEmail = ""
sValueName = "Address2"
lCode = oBilling.GetValue(sEmail, sValueName, x)
MsgBox lCode & " " & x
End Sub

The head of ACME Billing Information Systems decides that Address2 is too restrictive and the column needs to be broken into three columns: City, State, and ZipCode. If ACME had written separate code to interface to the database in its billing system and web page, both systems would need to be rewritten and tested, as would any another system that interfaced with those tables. Fortunately, ACME used a single DLL, so only one component needs to be rewritten and tested.

Listing 17.8 contains the code that needs to be modified to accommodate the new database structure.

Listing 17.8  Billing Class Interface to the Database with the New Database Scheme

Case "Address2"
        sQuery = "SELECT City, State, ZipCode FROM Region, Customer WHERE EmailAddress = `" & sIdentifier & _
                 "` AND Customer.Region = Region.ID "
    Case "City"
        sQuery = "SELECT City FROM Region, Customer WHERE EmailAddress = '" & sIdentifier & _
                 "` AND Customer.Region = Region.ID "
    Case "State"
        sQuery = "SELECT State FROM Region, Customer WHERE EmailAddress = '" & sIdentifier & _
                 "` AND Customer.Region = Region.ID "
    Case "ZipCode"
            sQuery = "SELECT ZipCode FROM Region, Customer WHERE EmailAddress = '" & sIdentifier & _
                     "` AND Customer.Region = Region.ID "
    Case Else
        GetValue = ILLEGAL_VALUE_NAME
End Select
`if the value name is valid then continue
If GetValue = 0 Then
    `get the value
    Set rs = m_DB.OpenRecordset(sQuery, dbOpenSnapshot)
    If Not rs.EOF Then
        If sValueName <> "Address2" Then
            vValue = rs(0)
        Else
            `special case for Address2
            vValue = rs!City & ", " & rs!State & " " & rs!ZipCode
        End If
    Else
        GetValue = NO_RECORD_FOUND
    End If
End If

The new database structure is masked by the ActiveX DLL for the existing system, while additional functionality is provided for future needs. Notice that if you pass Address2 to the GetValue function, the correct result is still returned. Also, you could pass City, State, or ZipCode and get only the desired information.

From Here...

This chapter explains the uses and advantages of server-side programming. You've learned what should go on to the client and what to the server. This chapter also explains some of the advantages of using various languages and software. It illustrates the advantages of using a component between the web server and database server. To learn more about server-side programming, see the following chapters:


Previous chapterNext chapterContents


© Copyright, Macmillan Computer Publishing. All rights reserved.