Appendix C

Delivering an Interactive Introduction Service


Database Design: Selections Table

The Selections table provides a structure for tracking members in relation to other members. When a member requests an introduction or responds to a request for an introduction, the Selections table tracks the user's choices. This table provides a mechanism for tracking the status of an evolving introduction as it moves from an anonymous request from one member to an acceptance or unfortunate rejection from another member.

The Selections table enables the Active Server Pages to evaluate and dynamically display different pages for members, depending on the status of current introductions in process for a particular member. This information defines both the information displayed to a member and the toolbar options available at any given time for that member. The table structure for managing the status and history of introductions turns out to be quite simple; in fact, the entire table is made up of only the 6 fields shown in Table C.1.

Table C.1 Selections Database Design Specification, Including Field Level Information

Field Name

DataType

Description

SelectID

Number (Long)

Primary key

SelectorMemberID

Number (Long)

Member ID of initiating member

SelectedMemberID

Number (Long)

Member ID of receiving member

SelectCreateDate

Date/Time

Date of initial selection

SelectFinalDate

Date/Time

Date of completed/final response

SelectStatus

Number (Long)

Current/final status of selection

Finding Other Members

The process of searching for members involves, not only the searching of active members based on criteria in their profiles, but also the active use of the Selections table to automatically filter out the members who have been previously selected. This filtering process prevents a member from having to continually scroll through a history of their past rejections or failed love connections. The key components utilized in a search include the Ideal Mate information, which allows the Service to automatically default information into the search criteria for a member; the Member Profile, which provides the information evaluated during the search; and the Selections table, which filters to limit the results returned.

The Search Pages involve a series of three .asp files that are dynamically created, including the initial Search Page, the resulting summary display of results, and the Member Profile, which allows members to request introductions.

Initial Search Page

The initial Search Page displayed in Figure C.1 defaults the Ideal Mate information and enables the member to customize the search criteria to either broaden or narrow the types of members that will be returned for display and possible selection.

Figure C.1

The Initial Search Page enables the member to begin a search of the member database.

The Service automatically filters out past rejections to save the member redundancy in the search process. And the search will also automatically include specific constraints based on the member's profile to avoid finding members of the wrong gender.

The Active Server Page for searching looks up the current member, based on his logged-on session variable, which stores his member ID and uses the Ideal Mate information to populate defaults into the search criteria. As illustrated by the session (nextmemberid) variable, the system also limits the number of selections displayed on the results page and allows the user to move through subsequent pages to display additional members. This next page technology, while not trivial to implement, allows you to manage the volume of data downloaded to any single page. The next page functionality becomes increasingly important in services like this one in which graphic images are displayed for each record found in the database. Listing C.1 illustrates the code utilized to provide the searching user with default values automatically populated into the selection parameters they can set.

Listing C.1 SEARCH.ASP-Initial Search Page

<!--#include file="validate.asp"-->

<%

  Set Conn = Server.CreateObject("ADODB.Connection")

  Conn.Open("firstsite")

  session("nextmemberid") = 0

  membernum = session("memberid")

  sql = "SELECT * FROM Members WHERE MemberID=" & membernum & ";"

  Set rs = Conn.Execute(sql)

  Set rsRace = Conn.Execute("SELECT * FROM AdminParameters where (systypeparam = 1) order by paramvalue;")

  Set rsReligion = Conn.Execute("SELECT * FROM AdminParameters [ic:ccc]where (systypeparam = 2) order by paramvalue;")

  Session("SearchPagesDisplayed") = 1

%>

<html><head>

<title>Search for your Ideal Mate</title>

</head>

<body bgcolor="#FFFFFF" text="#0000A0">

<table border=1 cellpadding=5 cellspacing=0 width=604>

<tr><td>

Our search wizard works within your constraints to help

 you find exactly who you are looking for.  Search

 with as many or as few criteria as you like.

...

 we let 90's technology work to your advantage.<p>

<form action="searchrun.asp" target="_top" method="POST">

<input type=hidden name="profprefid" value="<%=rs("ProfPrefID")%>">

...

Executing the Search and Displaying a Result Set

The Active Server Page named searchrun.asp either executes a direct search if a member ID was directly entered, or it runs a parameter-based search of the member table based on the more comprehensive criteria entered. The searchrun.asp also manages the next page feature, which allows members to display additional records if their searches return too many members. The display of the page allows the member to drill into a detailed Member Profile page by clicking on any photo displayed in the results page.

The execution of the searchrun.asp performs a database search, resulting in, not only a listing of the top 10 members found, but also a complete list of members found, enabling the user to page back and forth through the complete result set. Building a custom SQL statement requires a series of tests and field validations, based on the form data passed in by the search.asp page. The comprehensive logic illustrated in Listing C.2 details the complicated construction of a custom SQL statement for processing.

Listing C.2 SEARCHRUN.ASP-Section of the searchrun.asp file, Which Constructs the Custom SQL Statement for Execution

<!--#include file="validate.asp"-->

<%

    Set Conn = Server.CreateObject("ADODB.Connection")

    Conn.Open("firstsite")

'Tracking next page feature

' -------------------------------------------

If (not isempty(request.form("btn"))) or (Session("SearchPagesDisplayed") > 4) then 

   session("nextmemberid") = 0

End If

' -------------------------------------------

' Don't mix gay/hetero, set appropriate sql

' -------------------------------------------

sql = "SELECT ProfSex, ProfPrefID FROM Members WHERE MemberID=" & session("MemberID") & ";" 

Set rs2=Server.CreateObject("ADO.Recordset")

rs2.Open sql, Conn,1

ProfPrefID = rs2("ProfPrefID")

If rs2("ProfSex") = rs2("ProfPrefID") Then

 sqlsex = " AND (Members.ProfSex = Members.ProfPrefID) "

Else 

 sqlsex = " AND (Members.ProfSex <> Members.ProfPrefID) "

End If

rs2.close

'------------------------

'Test Direct or Full Lookup

'------------------------

if request.form("direct") <> "" then

'------------------------

'Direct Check

'------------------------

sql = "SELECT Top 10 Members.MemberID, Members.FName, Members.LName, [ic:ccc]Members.City, members.admingraphics FROM Members "

if isnumeric(request.form("direct")) = -1 then

  sql = sql & " WHERE ((members.profsex =" & request.form("profprefid") & ")[ic:ccc] AND ((Members.memberid)=" & request.form("direct") & ") AND ((Members.memberid)<>" & [ic:ccc]session("memberid") & ") AND ((Members.AdmStatus)=1) AND[ic:ccc] ((Members.AdmPublic)=Yes))" & sqlsex & " Order By Members.MemberID;"

else 'First Name Search

  sql = sql & " WHERE ((members.profsex =" & request.form("profprefid") & ")[ic:ccc] AND ((Members.FNAME)='" & request.form("direct") & "') AND [ic:ccc]((Members.memberid)<>" & session("memberid") & ") AND [ic:ccc]((Members.AdmStatus)=1) AND ((Members.AdmPublic)=Yes))" [ic:ccc]& sqlsex & " Order By Members.MemberID;"

end if

else

'------------------------

'Full Search

'------------------------

sql = "Select Top 11 members.admingraphics, members.fname, Members.LName[ic:ccc], members.memberid, members.city from members where "

  if request.form("idlRaceID") > 0 then

      sql = sql & " Members.profRaceID =" & request.form("idlRaceID") & " and "

  end if

  if request.form("idlRlgnID") > 0 then

      sql = sql & " Members.profRlgnID =" & request.form("idlRlgnID") & " and "

  end if

  select case request.form("idlheightflag")

    case 0

    case 1 

      sql = sql & "((Members.profHeightf * 12) + (Members.profHeightI)) [ic:ccc]<= " & ((request.form("idlHeightF") * 12) + [ic:ccc]request.form("idlHeightI")) & " and "

    case 2

      sql = sql & "((Members.profHeightf * 12) + (Members.profHeightI)) [ic:ccc]>= " & ((request.form("idlHeightF") * 12) + [ic:ccc]request.form("idlHeightI")) & " and "

  end select

  if request.form("idlSmkgID") = 1 then

      sql = sql & " Members.profSmkgID =" & "0" & " and "

  end if

  if request.form("idlDrkgID") = 1 then

      sql = sql & " Members.profDrkgID =" & "0" & " and "

  end if

  if not request.form("idlagelow") = "" and not request.form("idlagehigh") = "" then

      doblow = date - (request.form("idlagelow") * 365)

      dobhigh = date - ((request.form("idlagehigh") + 1) * 365)

      sql = sql & " (Members.profdob between #" & dobhigh & "# and #" & doblow & "#) and "

  end if

'Insert SQLsex or Gender Criteria portion of SQL

  sql = sql & " ((members.profsex =" & request.form("profprefid") & ")[ic:ccc] AND (Members.memberid<>" & session("memberid") & ") [ic:ccc]and (Members.AdmStatus=1) AND (Members.AdmPublic=Yes)" & sqlsex

  

  if request.form("idllocflag") <> 0 then

      sql = sql & " and ((Members.HMAreaCode = " & "'"[ic:ccc] & request.form("idllocarea1") & "'" & ") or " 

      sql = sql & "(Members.HMAreaCode = " & "'" & [ic:ccc]request.form("idllocarea2") & "'" & "))"

  end if

  sql = sql & " and (Members.MemberID >= " & [ic:ccc]session("nextmemberid") & ")) Order By Members.MemberID;"

  

end if

' --------------------------------

'Execute Search

' --------------------------------

Set rs=Server.CreateObject("ADO.Recordset")

rs.Open sql, Conn,1  

%>

...

Once the SQL statement has been constructed and executed, the task now turns to displaying the results. Using graphic images stored in a predefined directory and given names based on the IDs in the Member Profile, providing the capability to page through the search results is a deceptively difficult challenge. Listing C.3 illustrates the creation of the display page and record tracking feature to enable the paging logic.

The key aspects of the paging logic include the assumption that records are sorted by ID number, and, therefore, by searching for ID numbers greater than the last one displayed, you will return additional non-overlapping records. In addition, a Session property is utilized as a counter to determine which page or set of records the member currently is displaying. Finally, the page defaults a series of hidden form fields to the values that have been input for the search. Defaulting the values to hidden form fields enables the page to rerun itself, retrieving all of the information for rebuilding the search directly from the form fields. Other approaches for optimizing this type of paging logic might include storing the RecordSet as a Session property and retrieving a full RecordSet at the initial search.

Listing C.3 SEARCHRUN.ASP-Display Section of the searchrun.asp file, Which Manages the Next Page Feature

<html><head>

<title>Search Results Profile</title>

</head>

<body bgcolor="#FFFFFF" text="0000A0">

<form action="searchrun.asp" TARGET="_top" method="POST">

<table border=1 cellpadding="0" cellspacing="0" width=600>

<tr><td colspan=5><img src="images/searchrun.gif"

 align=bottom width=600 height=30></td></tr>

<tr>

<%

'------------------------

'Display first ten results

'------------------------

  i=0

  Do While (Not RS.EOF) 

  i = i + 1     

  if i < 11 then

     if rs("admingraphics") = 0 then 

        imagename = "Default.tn"

     else

        imagename = rs("memberid") & ".tn"

     end if

%>

     <td align=center>

     <a href="profile.asp?id=1&memberid=<%=rs("memberid")%>">

<img src="/images/profile/<%=imagename%>.jpg"

 align=bottom border=0 width=100 height=85></a><br>

     <% line1 = rs("fname") & " " & left(rs("lname"),1)[ic:ccc] & " </strong> " & rs("memberid") %>

     <font size=1><strong><%= line1 %><br><%=rs("city")%></font></center>

     </td>

<%

     if i/5 = int(i/5) then response.write "</tr><tr>"

  Else

     'Set next page memberID

     session("nextmemberid") = cint(rs("MemberID"))

  End If

  RS.MoveNext

  Loop

  RS.Close

%>

</tr>

<%

'------------------------

'O Results found in search

'------------------------

If i = 0 then %>

   <tr><td colspan=5 width=600><b>No members met your 

search criteria.  You may wish to try a less specific

 search criteria.</b></td></tr>

<% End If %>

<%

'------------------------

'Add Next Page feature

'------------------------

 If (i = 11) and (Session("SearchPagesDisplayed") < 4) then %>

   <MAP NAME="nextpage">

   <AREA SHAPE="RECT" COORDS="20,1 147,20">

   </MAP>

   <tr><td colspan=5 width=600><INPUT NAME="submit"[ic:ccc] INPUT TYPE="IMAGE" SRC="/images/nextpage.gif" BORDER=0[ic:ccc] USEMAP="#nextpage"></tr></td>

<% Else %>

   <% Session("SearchPagesDisplayed") = 0 %> 

   <tr><td colspan=5 width=600><img src="/images/blackbar.gif" [ic:ccc]align=bottom width=600 height=24></td></tr>

<%'------------------------

End If %>

</table>

<%If ProfPrefID = 0 then%>

   <center><img src="gclikani.gif" width=300 height=80 border=0></center>

<%Else%>

   <center><img src="bclikani.gif" width=300 height=80 border=0></center>

<%End If

'------------------------

'Store hidden values for page feature

'------------------------%>

<INPUT NAME="direct"[ic:ccc] VALUE="<%=request.form("direct")%>" TYPE=HIDDEN>

<INPUT NAME="profprefid"[ic:ccc] VALUE=<%=request.form("profprefid")%> TYPE=HIDDEN>

<INPUT NAME="idlraceid"[ic:ccc] VALUE=<%=request.form("idlraceid")%> TYPE=HIDDEN>

<INPUT NAME="idlrlgnid"[ic:ccc] VALUE=<%=request.form("idlrlgnid")%> TYPE=HIDDEN>

<INPUT NAME="idlheightflag"[ic:ccc] VALUE=<%=request.form("idlheightflag")%> TYPE=HIDDEN>

<INPUT NAME="idlheightf"[ic:ccc] VALUE=<%=request.form("idlheightf")%> TYPE=HIDDEN>

<INPUT NAME="idlheighti"[ic:ccc] VALUE=<%=request.form("idlheighti")%> TYPE=HIDDEN>

<INPUT NAME="idlsmkgid"[ic:ccc] VALUE=<%=request.form("idlsmkgid")%> TYPE=HIDDEN>

<INPUT NAME="idldrkgid"[ic:ccc] VALUE=<%=request.form("idldrkgid")%> TYPE=HIDDEN>

<INPUT NAME="idlagelow"[ic:ccc] VALUE=<%=request.form("idlagelow")%> TYPE=HIDDEN>

<INPUT NAME="idlagehigh"[ic:ccc] VALUE=<%=request.form("idlagehigh")%> TYPE=HIDDEN>

<INPUT NAME="idllocflag" [ic:ccc]VALUE=<%=request.form("idllocflag")%> TYPE=HIDDEN>

<INPUT NAME="idllocarea1" [ic:ccc]VALUE="<%=request.form("idllocarea1")%>" TYPE=HIDDEN>

<INPUT NAME="idllocarea2" [ic:ccc]VALUE="<%=request.form("idllocarea2")%>" TYPE=HIDDEN>

</form>

</body>

</html>

<%end if%>

<%Session("SearchPagesDisplayed") = Session("SearchPagesDisplayed") + 1 %>

     

Displaying an Individual Member for Introduction

Once a user has identified and selected a suitable member by clicking on a photograph from the search results page, a Member Profile is displayed with a custom toolbar. The Member Profile page is invoked from a number of sources, and so the toolbar varies quite dramatically from one use to the next. When the Member Profile is displayed as the result of a search, the options primarily include the capability to request an introduction. The request creates a selection record with initial status, which displays the member on the Start Page of both the selected and selecting member.

The basic Member Profile page includes comprehensive profile information about the member, but the last name, phone number, and Mail information is not displayed at this point. That information is displayed only after both members have approved the introduction process.

The Active Server Pages used to generate the Member Profile page and navigation toolbar become a little more complicated because of the use of frames. Frames are used extensively throughout the Service site, and although they do not fundamentally change the way Active Server Pages are used, you must understand that multiple independent pages are being requested and executed for the display of a single request.

Frames and Active Server Pages

Frames involve a Frame Set page that manages which pages are called; although ASP execution properly works on all frames, they are independent pages, and, therefore, you must be careful in your scoping of request-based variables.

Profile Display Frame Set (Manager)

The initial page call requests the profile.asp page, which manages the calling of other .asp files and the passing of request-based variables into those pages. The additional pages called include:

Many features of the site rely on an initial call to a Frame Set as illustrated in the sections for Editing, Archiving, and more. Listing C.4 illustrates the basic setup of a Frame Set.

Listing C.4 PROFILE.ASP-Frame Manager .asp File Responsible for Calling All Individual Frame .asp Files

<!--#include file="validate.asp"-->

<HTML>

<TITLE>Love@1st-Site - Profile Page</TITLE>

<%session("id")=request.querystring("id")%>

<FRAMESET ROWS="41, *, 33">

<FRAME SRC="profile_top.asp" NAME="toolbar"[ic:ccc] MARGINWIDTH=0 NORESIZE SCROLLING="no">

<FRAME SRC="profile_display.asp?memberid=[ic:ccc]<%=request.querystring("memberid")%>" NAME="bottom" [ic:ccc]NORESIZE MARGINWIDTH=0 SCROLLING="auto">

<FRAME SRC="profile_bot.asp?memberid=[ic:ccc]<%=request.querystring("memberid")%>" NAME="top" [ic:ccc]MARGINWIDTH=0 NORESIZE SCROLLING="no">

</FRAMESET>

<NOFRAME>

This page requires Netscape 2.0 or higher, Microsoft

 Explorer 3.0 or  AOL 3.0.

<p>

Please download one of the previously mentioned

 browsers to view this page.

</NOFRAME>

</HTML>

The Top and Bottom frames provide toolbar/navigation features whereas the center frame ignores the logic associated with providing custom toolbars and focuses on the more standardized display of a member's profile.

Center Frame-Profile Display

The profile display relies upon the selected member ID request variable passed into the page and then uses the session variables to determine what options have been enabled on the current page display; i.e. if this represents a mutually consented introduction display, additional information including last name, phone number, and Mail may be displayed.

The code from the profile_display.asp illustrated in Listing C.5 provides the lookups and evaluations conducted prior to generating the custom HTML-based display. The following SQL statement and evaluations highlight the lookups to populate the HTML page and the rule-based evaluations based on a session variable to determine how much confidential information to include on this page. The session variable is configured when this page call begins from the Start Page, reflecting, not a new introduction request, but an introduction request that already has been created and assigned a status flag.

Listing C.5 PROFILE_DISPLAY.ASP-Format and Display of the Requested Member's Profile Information by the Profile Display

<!--#include file="validate.asp"-->

<%

  Set Conn = Server.CreateObject("ADODB.Connection")

  Conn.Open("firstsite")

  sql = "SELECT * FROM Members WHERE MemberID=" & Request("MemberID") & ";"

  Set rs = Conn.Execute(sql)

'------------------------

'Request display values from AdminParameters

'------------------------

sql="SELECT ParamValue From AdminParameters WHERE SysParamID=" & rs("ProfRaceID")

  Set rsRace = Conn.Execute(sql) 

sql="SELECT ParamValue From AdminParameters WHERE SysParamID=" & rs("ProfRlgnID")

  Set rsReligion = Conn.Execute(sql) 

sql="SELECT ParamValue From AdminParameters WHERE SysParamID=" & rs("ProfBodyID")

  Set rsBody = Conn.Execute(sql) 

sql="SELECT ParamValue From AdminParameters WHERE SysParamID=" & rs("ProfEdID")

  Set rsEduc = Conn.Execute(sql) 

sql="SELECT ParamValue From AdminParameters [ic:ccc]WHERE SysParamID in (" & rs("ProfMusic") & ")"

  Set rsMusic = Conn.Execute(sql) 

  sql = "SELECT ParamValue From AdminParameters [ic:ccc]WHERE SysParamID in (" & rs("ProfQ1ID") & ")"

  Set rsQuestion = Conn.Execute(sql)

'------------------------

  If rs("AdminGraphics") = 0 then

     PictureHead = "default.hd.gif"

     PictureFull = "default.fl.gif"

  Else

     PictureHead = rs("MemberID") & ".hd.jpg"

     PictureFull = rs("MemberID") & ".fl.jpg"

  End If

'------------------------

  Set DBConn=Server.CreateObject("ADODB.Connection")

  DBConn.Open("firstsite")

  sql = "SELECT ProfAct, ProfQ1Info, ProfWhat FROM Members WHERE MemberID=" & Request("MemberID") & ";"

  Set rsMemo=Server.CreateObject("ADODB.Recordset")

  rsMemo.Open sql, DBConn,3 

'------------------------

'Determine what confidential info to display

'------------------------

  If session("lookupstatus") = 3 then 'Accepted

     fullname = rs("Fname") & " " & rs("Lname")  'Variable named Fullname 

     If rs("publicphone") = 1 then

       homephone = rs("hmareacode") & " " & rs("hmphone")

       workphone = "Not Available"       

     ElseIf rs("publicphone") = 2 then

       homephone = "Not Available"

       workphone = rs("wkareacode") & " " & rs("wkphone")

     ElseIf rs("publicphone") = 0 then

       homephone = rs("hmareacode") & " " & rs("hmphone")

       workphone = rs("wkareacode") & " " & rs("wkphone")        

     End If

  Else

     homephone = ""

     workphone = ""

     fullname = rs("Fname") & " " & Left(rs("Lname"), 1)

  End If

'------------------------

%>

...

Top Frame-Service-Wide Toolbar

The top frame or profile_top.asp evaluates session status variables to determine what toolbar options to display. This evaluation includes a wide variety of possibilities because the profile.asp Frame Set can be called for many purposes, ranging from a member maintaining her own profile to a member getting access to profile from a search. The specific values are less important than the idea that statuses are used to custom generate different toolbar options. In Listing C.6, many of the options are actually the same for the Introduction Service, but the graphics displayed vary.

Listing C.6 PROFILE_TOP.ASP-Top Frame, Providing System-Wide Navigation Options

<HTML>

<BODY BGCOLOR="#ffffff">

<table cellspacing=0 cellpadding=0 border=1 width=600>

<tr><td><LEFTMARGIN=0>

<%If session("comingfrom") = "l" then%>

   <MAP NAME="b_select">

<AREA SHAPE="RECT" COORDS="319,1 381,30" HREF="profile.asp?memberid=[ic:ccc]<%=session("memberid")%>" TARGET="_top">

<AREA SHAPE="RECT" COORDS="384,1 439,30" HREF="searchframe.asp" TARGET="_top">

<AREA SHAPE="RECT" COORDS="444,1 506,30" HREF="archive.asp" TARGET="_top">

<AREA SHAPE="RECT" COORDS="511,1 597,30" HREF="start.asp" TARGET="_top">

   </MAP>

   <IMG SRC="b_select.gif" BORDER=0 USEMAP="#b_select">

...

<%Else%>

   <MAP NAME="update">

<AREA SHAPE="RECT" COORDS="319,1 381,30" HREF=[ic:ccc]"profile.asp?memberid=<%=session("memberid")%>" TARGET="_top">

<AREA SHAPE="RECT" COORDS="384,1 439,30" HREF="searchframe.asp" TARGET="_top">

<AREA SHAPE="RECT" COORDS="444,1 506,30" HREF="archive.asp" TARGET="_top">

<AREA SHAPE="RECT" COORDS="511,1 597,30" HREF="start.asp" TARGET="_top">

   </MAP>

   <IMG SRC="update.gif" BORDER=0width=600 height=30  USEMAP="#update">

<%End If%>

<%session("comingfrom")=""%>

</td></tr></table></BODY></HTML>

Bottom Frame-Introduction Specific Options

The bottom frame or profile_bot.asp evaluates session status variables to determine what toolbar options to display in the top toolbar; however, the set of options provides choices that are specific to the Introduction process rather than choices that enable Service-wide routing. This frame manages, not only the introduction process options, but also the member's personal profile editing options as well. Listing C.7 provides a comprehensive look at managing custom toolbar options.

Listing C.7 PROFILE_BOT.ASP-Introduction-Specific Navigation Options for the Member

<HTML><BODY BGCOLOR="#ffffff">

<table cellspacing=0 cellpadding=0 border=1 width=600><tr><td>

<%

if cint(request("memberid")) = cint(session("memberid")) then

'------------------------------------------

' Option 1 - Editing Profile

'------------------------------------------

%>

<MAP NAME="ud_menu">

<AREA SHAPE="RECT" COORDS="20,1 93,24"[ic:ccc] HREF="editacct1_frame.asp" target="_top">

<AREA SHAPE="RECT" COORDS="97,1 148,24"[ic:ccc] HREF="editacct2_frame.asp" target="_top">

<AREA SHAPE="RECT" COORDS="150,1 237,24"[ic:ccc] HREF="editacct3_frame.asp" target="_top">

<AREA SHAPE="RECT" COORDS="241,1 289,24"[ic:ccc] HREF="editacct5_frame.asp" target="_top">

</MAP>

<IMG SRC="ud_menu.gif" BORDER=0 USEMAP="#ud_menu">

<%

else

Select Case session("lookupstatus") 

'------------------------------------------

Case 0   ' Initial Selection , Allows Request Introduction

'------------------------------------------

%>

<MAP NAME="request">

<AREA SHAPE="RECT" COORDS="20,1 147,30" HREF="profile_process.asp?[ic:ccc]decision=0&memberid=<%=request("memberid")%>" target="_top"></MAP>

<IMG SRC="request.gif" BORDER=0 USEMAP="#request">

<%

'------------------------------------------

Case 1  ' Checking on Status of Selection, Allows Email

'------------------------------------------

%>

<MAP NAME="sendbott">

<AREA SHAPE="RECT" COORDS="20,1 147,20" HREF="profile_process.asp?[ic:ccc]decision=4&memberid=<%=request("memberid")%>" target="bottom"></MAP>

<IMG SRC="sendbott.gif" BORDER=0 USEMAP="#sendbott">

<%

'------------------------------------------

Case 2 ' Time to make a decision, Allows Yes, No, Not at this time

'------------------------------------------

%>

<MAP NAME="yesno">

<AREA SHAPE="RECT" COORDS="20,1 54,24" HREF="profile_process.asp?[ic:ccc]decision=1&choice=1&memberid=<%=request("memberid")%>" target="_top">

<AREA SHAPE="RECT" COORDS="56,1 163,24" HREF="profile_process.asp?[ic:ccc]decision=1&choice=3&memberid=<%=request("memberid")%>" target="_top">

<AREA SHAPE="RECT" COORDS="166,1 191,24" HREF="profile_process.asp?[ic:ccc]decision=1&choice=2&memberid=<%=request("memberid")%>" target="_top">

<AREA SHAPE="RECT" COORDS="195,1 287,24" HREF="start.asp" target="_top">

</MAP>

<IMG SRC="yesno.gif" BORDER=0 USEMAP="#yesno">

<%

'------------------------------------------

Case 3 ' Yes Disply, Enhanced Information

'------------------------------------------

%>

<IMG SRC="startbot.gif" BORDER=0>

<%

End Select

end if

session("lookupstatus") = 0

%>

</td></tr></table></BODY></HTML>

The Introduction Process and the Start Page

The heart of the Introduction Service is the process by which members introduce themselves to other members. This Introduction Process involves extensive logic to manage the various stages of the introduction process: from the initial request for introduction, to the acceptance or rejection by the selected member, to the acknowledgment of the answer by the selecting member. In the previous search area, we explored the mechanism that members use for the initial request for introduction. From that point on, a member manages the process from her Start Page, which has a custom display that is based on the selections she has made and the requests for introduction that other members have made to that member. The basic flow of the Introduction Process after the initial selection goes to the Member Profile page where a member can either accept or reject an introduction request.

The Start Page, Controlling the Introduction Process

Like the profile area, frames drive the Start Page area. Also like the profile area, the frames provide navigation toolbars and specific introduction-related choices. The roles of the specific frames include:

The start.asp file provides Frame Set control in a similar way to the profile.asp. This includes very little use of Active Server Pages features other than the Server-Side Include and processing of the validate.asp page. The individual frames deliver all of the dynamic page content. The top frame does not currently vary by member, and while important differences exist for the member between the left and right page, the code is surprisingly similar.

Start Top: Service-wide Navigation

The top frame displays a standard set of options, which, at this time, do not vary by user; therefore, no specific processing takes place in the top frame other than initializing several request variables in hyperlinks for use on subsequent page requests.

Start Left: Other Member's Requests

In contrast to the top, the start left does a lookup based on member ID to identify all of the records in the Selections table with an active status for display on the user's Start Page. Depending on the status of a user's particular selection record, the member has the capability to change the selections status.

The left page executes a search that is driven primarily by a join between the Member table and the Selections table as illustrated in Listing C.8. The filtering of this SQL statement is based on the member ID selected and the record's current status. Following the execution of the query, the processing page invoked evaluates the status of the introduction to determine whether to return to the Start Page or to display the Profile Page.

Listing C.8 START_LEFT.ASP-Frame for Displaying Graphic Image and Information on Members that have Selected the Logged-on User

<html><head><title>left</title></head>

<body bgcolor="#FFFFFF" text="0000A0"><LEFTMARGIN=0>

<table border=1 cellpadding=0 cellspacing=0 width=296 align-"right">

<%

  Set Conn = Server.CreateObject("ADODB.Connection")

  Conn.Open("firstsite")

  sql = "SELECT Top 40 selections.SelectCreateDate, selections.SelectFinalDate,[ic:ccc] selections.selectid, selections.SelectStatus, selections.SelectorMemberID,[ic:ccc] Members.Admingraphics, Members.FName, Members.LName, Members.City, * FROM Members[ic:ccc] INNER JOIN selections ON Members.MemberID = selections.SelectorMemberID [ic:ccc]WHERE (((selections.SelectStatus)<5) AND ((selections.SelectStatus)<>2)[ic:ccc] AND ((selections.SelectStatus)<>3) AND ((selections.SelectedMemberID)="

  sql = sql & session("memberid") & ")) ORDER BY selections.SelectFinalDate DESC;"

Set RS = conn.Execute(sql)

If RS.EOF Then

 Response.write "<center><b>No members have selected you.</b></center>"

  End If

  Do While Not RS.EOF

  line1 = rs("fname") & " " & left(rs("lname"),1) [ic:ccc]& " " & rs("selectormemberid") & "<br> " & rs("city")

%>

<tr><td align=center width=192>

<font size=2><strong><%=line1%><br></strong>

<%

'----------------------------------

'Display Message Depending on Status

'----------------------------------

Select Case rs("selectstatus")

Case 0 'Open Selection

  msg = "Selected On " & rs("selectcreatedate") & "<br> Status Open"

Case 1 'Yes Response

  msg = "Responded Yes on " & rs("selectfinaldate") 

Case 2 'No Response

  msg = "Responded No Thank You <br>on " & rs("selectfinaldate") 

Case 3 'Not at this time

  msg = "Responded Not at this time <br>on " & rs("selectfinaldate") 

Case 4 'Went Inactive

  msg = "They went Inactive <br>on " & rs("selectfinaldate") 

End Select

  Response.write msg

'----------------------------------

%>

</font></td><td width=102>

<%

  if rs("admingraphics") = 0 then 

     imagename = "Default.tn"

  else

     imagename = rs("selectormemberid") & ".tn"

  end if

%>

<a href="profile_evaluate.asp?selectid=<%=rs("selectid")%>[ic:ccc]&status=<%=rs("SelectStatus")%>&id=3&memberid=<%=rs("selectormemberid")%>[ic:ccc]" target="_top"><img src="/images/profile/<%=imagename%>.jpg"[ic:ccc] align=top border=0 width=100 height=85></a>

</td></tr>

<%

  RS.MoveNext

  Loop

  RS.Close

%>

</table></body></html>

<%Conn.Close%>

Start Right: Member's Pending Requests

The right page illustrates the status of member selections made by the logged-on member. Like the left page, the right page builds a query that is based on a join of the member table. But in this case, the join is on the selector member ID and the selected member ID. The query also filters, based on status. Listing C.9 illustrates the code to execute the query and to generate the list of selected members customized by each member's current status.

Listing C.9 START_RIGHT.ASP-Frame for Displaying a List of Members that have been Selected by the Logged-on Member

<html><head><title>Right</title></head>

<body bgcolor="#FFFFFF" text="0000A0">

<LEFTMARGIN=0><div align=left>

<table border=1 cellpadding=0 cellspacing=0 width=300>

<%

  Set Conn = Server.CreateObject("ADODB.Connection")

  Conn.Open("firstsite")

  sql = "SELECT Top 40 selections.SelectCreateDate, selections.SelectFinalDate,[ic:ccc] selections.selectid,  selections.selectfinaldate, selections.SelectStatus,[ic:ccc] selections.SelectedMemberID, Members.FName, Members.LName, Members.City,[ic:ccc] Members.Admingraphics, * FROM Members INNER JOIN selections ON Members.MemberID[ic:ccc] = selections.SelectedMemberID WHERE (((selections.SelectStatus)<5)[ic:ccc] AND ((selections.SelectorMemberID)="

sql = sql & session("memberid") & ")) ORDER BY selections.SelectFinalDate DESC;"

  Set RS = Conn.Execute(sql)

  If RS.EOF Then

     Response.write "<center><b>You have not made any selections.<br>[ic:ccc](Click on <font color=#FF0000>New Search</font> button above)</b></center>"

  End If

  Do While Not RS.EOF

  line1 = rs("fname") & " " & left(rs("lname"),1) & " " &[ic:ccc] rs("selectedmemberid") & "<br> " & rs("city")

%>

<tr><td width=100>

<%

  if rs("admingraphics") = 0 then 

     imagename = "Default.tn"

  else

     imagename = rs("selectedmemberid") & ".tn"

  end if

%>

<a href="profile_evaluate.asp?selectid=<%=rs("selectid")%>&status=[ic:ccc]<%=rs("SelectStatus")%>&id=2&memberid=<%=rs("selectedmemberid")%>" [ic:ccc]target="_top"><img src="/images/profile/<%=imagename%>.jpg" [ic:ccc]align=top border=0 width=100 height=85></a>

</td><td align=center width=192>

<font size=2><strong><%=line1%><br></strong> 

<%

'----------------------------------

'Display Message Depending on Status

'----------------------------------

Select Case rs("selectstatus")

Case 0 'Open Selection

  msg = "Selected On " & rs("selectcreatedate") & "<br> Status Open"

Case 1 'Yes Response

  msg = "Responded Yes on " & rs("selectfinaldate") 

Case 2 'No Response

  msg = "Responded No Thank You <br>on " & rs("selectfinaldate") 

Case 3 'Not at this time

  msg = "Responded Not at this time <br>on " & rs("selectfinaldate") 

Case 4 'Went Inactive

  msg = "Member went Inactive <br>on " & rs("selectfinaldate") 

End Select

  Response.write msg

'----------------------------------

%></font></td></tr>

<%

  RS.MoveNext

  Loop

  RS.Close

  Conn.Close

%>

</table></div></body></html>

The Evaluation Page

Once any graphic from either the left or the right page is clicked, it invokes the profile_evaluate.asp page, which can be thought of as a pre-processor of the status information, prior to redirecting the user into the profile area. The evaluation logic determines which options to provide members when they reach the profile_bot.asp as well as what information to display. In fact, if the status denotes rejection, the profile evaluate page actually redirects the member back to the Start Page while updating the Selections table status to remove that member from the displayed list.

The profile_evaluate.asp file illustrated in Listing C.10 demonstrates the extensive use of the Redirect feature to provide security and stability. The Redirect feature also enables the .asp files to be designed in a more module approach. If the status updates and redirection of the evaluation page were included on the display page, a refresh of the page would risk incorrect updates being applied to the Selections Status table.

Separating the update SQL statements from the display pages and using a response.Redirect feature can protect your system from refreshes and other unanticipated and hard to trap events that could cause invalid updates to your tables.

Listing C.10 PROFILE_EVALUATE.ASP-Evaluation of Selection Status to Determine Necessary Selections Status Updates and Member Routing

<%

 Set Conn = Server.CreateObject("ADODB.Connection")

 Conn.Open("firstsite")

'-----------------------------------------------------

'Initialize SelectID for working with selectin record

'-----------------------------------------------------

Session("lookupid") = cint(request.querystring("selectid"))

If request.querystring("id") = "2" then

   session("comingfrom") = "r"  'user clicked left side picture

ElseIf request.querystring("id") = "3" then

   session("comingfrom") = "l"  'user clicked right side picture

End If

'------------------------

'Evaluate Status of request

'------------------------

select case request.querystring("status")

Case "" 'No status, either edit profile or initial search results

  session("lookupstatus") = 0 'No Selection Yet

'------------------------

Case "0" 'Open Status No Choice Made Yet

'------------------------

  If request.querystring("id") = "2" then 'Selector

     'Check to see if profile selected has allowed email to be sent to him/her

sql="SELECT EOK FROM Members WHERE MemberID = " & request.querystring("memberid") & ";"

     Set rs = Conn.Execute(sql)

     if rs("EOK") = -1 then

        session("lookupstatus") = 1 'OK to send email

     else

        session("lookupstatus") = 4 '4 indicates don't allow email to be sent

     end if

     '-----------------------------------------------------

  elseif request.querystring("id") = "3" then ' Selected

     session("lookupstatus") = 2 'Checking to make decision

     '-----------------------------------------------------

  End If

'------------------------

Case "1" 'Yes In Process Status - Selector acknowledges Yes

'------------------------

  if request.querystring("id") = "2" then

         'set conn = session("conn")

         sql = "UPDATE Selections SET"

         sql = sql & " selections.selectstatus = 7"

         sql = sql & " WHERE selections.SelectID=" & Session("lookupid") & ";"

         Set rs = Server.CreateObject("ADO.Recordset")

         rs.Open sql,Conn,3

  end if

  session("lookupstatus") = 3

  session("lookupstatus2") = 2 'Flag for enhanced disply info

  '-----------------------------------------------------

'------------------------

Case "2" ' No In Process Status

'------------------------

  'Update to Status 5 

         'set conn = session("conn")

         sql="UPDATE Selections SET"

         sql=sql & " selections.selectstatus = 5"

         sql=sql & " WHERE selections.SelectID=" & request.querystring("selectid") & ";"

         Set rs = Server.CreateObject("ADO.Recordset")

         rs.Open sql,Conn,3

  response.redirect "start.asp"

'------------------------

Case "3" 'Not at this time In Process Status

'------------------------

  'Update to Status 6 if ID 2 or Selector

         'set conn = session("conn")

         sql="UPDATE Selections SET"

         sql=sql & " selections.selectstatus = 6"

         sql=sql & " WHERE selections.SelectID=" & request.querystring("selectid") & ";"

         Set rs = Server.CreateObject("ADO.Recordset")

         rs.Open sql,Conn,3

  response.redirect "start.asp"

'------------------------

Case "4" 'Inactive In Process Status

'------------------------

'If request.querystring("id") = "3" then 'Selector

        'Delete Record if ID 2 or Selector

         sql="Delete * from Selections"

         sql=sql & " WHERE selections.SelectID=" & request.querystring("selectid") & ";"

         Set rs = Server.CreateObject("ADO.Recordset")

         rs.Open sql,Conn,3

  'End IF

  response.redirect "start.asp"

'------------------------

Case "5" ' NO Final Status

'------------------------

  'This case should never be invoked ERROR

  response.redirect "start.asp"

'------------------------

Case "6" ' Not at this time Final, Searching OK and selected bys Archive

'------------------------

 'From Archive of Selected 

  session("lookupstatus") = 0

'------------------------

Case "7" ' Yes Final, no Search but both have archive

'------------------------

 'From Archive Selector or Selected

  session("lookupstatus") = 3

  session("lookupstatus2") = 2 'Flag for enhanced disply info

End Select

'------------------------

'------------------------

redirectpage = "profile.asp?memberid=" & request.querystring("memberid")

response.redirect redirectpage

Conn.Close

%>

Mail-driven Introduction Features

In addition to the features that members manage themselves in order to control the introduction process, the Service site has several Mail features. These features enable the system to use logic to generate batch Mail messages to members at various times and for different reasons. The key Mail features include:

This type of automated communication between the Internet site and the member community can facilitate going beyond the Web server to integrate other servers and services into the site's interactive experience.

From Here...

After having built an understanding of how to approach constructing a membership-based community and exploring the Introduction Service's example of building interactivity into the site experience, we need to now turn to the administrative and fee collection side of an Internet/intranet based business site.

The following two chapters begin a discussion of how to manage the fee collection process and how to enable site administrators to control the membership community and in general maintain the site.


© 1997, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.