日期:2010-12-13  浏览次数:21342 次

假设现在你要在站点上建立一个多页面的订货表单,从而执行从站点通过email发给订单书写人,并假定这些单独的页面、页面的个数以及页面上的输入域都可以根据实际要订购的产品而改变。

  如果我们将每个页面都分别提交给FrontPage的 email 向导或CGI 的email 程序,那么可怜的订单书写人就要为订单的每一页都收到一个单独的邮件信息。当然我们可以通过session变量、隐藏域或查询字符串将订货数据从一页传递到另一页,但是在内存中储存这些数据会造成应用程序不平衡,另外潜在地需要大量的脚本。而且当页面上的域变化时还必须要修改脚本代码,所以代码不太能够再利用。

  如果能够写出一套脚本可以用在所有这些订单页面中,只把HTML页面的设计留给WEB设计者,那就太好了。

  一个简单的答案是,将每个页面中的数据保存在一个文件中,然后将所有这些文件连接起,再将之用Email方式发送给订单书写人。这种方法另外还有一个好处是如果愿意可以在硬盘上保持临时文件,那么在晚些时候用户可以继续一个未完成的订单。最好的一点是,执行这一办法不需要第三方组件,而只需要session变量,ASP脚本和Scripting.FileSystemObject 对象。

  首先要为这些单独的页面数据文件确定唯一的名字,这样在订单结束时可以将它们放在一起,并且不会被应用程序中的其它文件所覆盖。同时,需要从单个session变量表示的文件进行聚合中,这样就不会偶然将一个旧session中的数据包含到当前的订单中。

  由IIS所提供的Session变量("SessionID")在一个Session过程中在网络服务器上是唯一识别的,但是到了后面,Session就可以被复制。(事实上,SessionID在以后会话Session时总是要被复制的,SessionID存储在客户机的一个cookie 中。当网络服务器从客户机中接收到一个过去会话的SessionID时,若它没有被另一个活动会话所使用,就使用相同的值,这样就不用向浏览器发送另一个cookie了,有关的信息可以参见微软MSDN上的Managing Sessions

  为了唯一识别session,我们要创建一个自己的session识别器Session("SessionToken"), 使用时间考验的方法:
向SessionID附加日期和时间。

Sub SetSessionToken
 dim dtTemp
 dim sDate
 dim sTime

 dtTemp = date
 sDate = Year(dtTemp) & Month(dtTemp) & Day(dtTemp)
 dtTemp = Time
 sTime = Hour(dtTemp) & Minute(dtTemp) & Second(dtTemp)
 Session("SessionToken") = Session.SessionID & "-" & sDate & "-" & sTime
End Function

  通过将SetSessionToken 封装成函数,可以轻易地修改算法来生成一个session 标志,而不用影响代码的其它部分。在第一页订单的顶端将调用SetSessionToken。

  每一页都要有一个唯一的页码,要将它附加到session 标志变量上去产生文件名。给页面使用任何一种标志都可以,但是在这里的应用程序中,页面必须要按照输入的顺序被输出,所以就使用一个捕捉这一顺序的页码。跟前面一样,将这个文件名算法封装到一个函数中,以后修改起来就很容易了。

Function BuildFilename(iPage)
' -- if the session has expired, return a null filename.
 If Session("SessionToken")="" Then
  BuildFilename = ""
 Else
  BuildFilename = Session("SessionToken") & iPage & ".txt"
 End If
End Function

  在订单第一页后面每一页的顶端,都调用WritePage函数将从前一页提交的数据写入文件。最后一页之后也调用这个函数。

Function WritePage(iPrevPage)
 dim sFilename
 dim objFSO
 dim objTS
 dim objField

 sFilename = buildFileName(iPrevPage)
 Set objFSO = CreateObject("Scripting.FileSystemObject")

 Set objTS = objFSO.OpenTextFile(sFilename, 2, True)

 ' -- note that using For .. Each on the Request.Form
 ' collection does not return the fields in any
 ' specific order.
 For Each objField in Request.Form
  ' -- write one field per line to the output file, name = value
  objTS.WriteLine objField & " = " & Request.Form(objField)
 Next

 objTS.Close
 Set objTS = nothing
 Set objFSO = nothing
End Function

  要记住每一页的数据都由后面一页来负责写入文件,所以第二页必须知道它是跟随第一页的,依次类推。用一个session 变量 CurrDataPage把当前表单数据页码从这一页的开始带到下一页的WritePage() 调用中,而不是在调用中使用每个页码的硬编码。一会儿就能看到,将所有页码结合起来的程序要知道最后一个页码是什么,所以使用一个子程序来给CurrDataPage 赋值,同时查看它是不是最后一页的页码。

< %
 Sub SetCurrPage(iPageNum)
  If iPageNum > Session("MaxDataPage") Then
   Session("MaxDataPage") = iPageNum
  End If
  Session("CurrDataPage") = iPageNum
 End Sub
% >

  这样,每一页(第一页除外)在脚本< BODY > 区的顶端都是这样的:

< %
 WritePage(Session("CurrDataPage"))
 SetCurrPage( {this page's number} )
% >

  而第一页脚本是:

< %
 SetSessionToken
 SetCurrPage( 1 )
% >

  数据的最后一页将被提交给一个确认页,这是任何电子商务站点上的标准步骤。我们的情况需要一个确认页,以提供一个机会来写出最后一页订单的数据,并建立传