每個開發(fā)人員面對的困難是預(yù)測用戶能夠或是將要做什么--這對于網(wǎng)絡(luò)開發(fā)人員來說就更為困 難,因為他的預(yù)測必須考慮到Web
的多樣性和缺乏真正的session控制機制。如果你已經(jīng)創(chuàng)建過一個使用表單的ASP應(yīng)用程序,也許你已經(jīng)遇到過一些奇怪的問題,如數(shù)據(jù)傳輸兩次,接收數(shù)據(jù)不完整,或者用戶報告表單顯示不正確。盡管你也插入了確認(rèn)數(shù)據(jù)所需的所有客戶機端和
服務(wù)器端的腳本,表單仍然會發(fā)生許多異常情況。這些異常情況與意外用戶行為或瀏覽器書簽的誤使用有關(guān)。本文將集中解決一些容易引起表單問題的典型情況:用戶意外地重復(fù)發(fā)送數(shù)據(jù),在多步驟表單中直接使用中間表單。
數(shù)據(jù)復(fù)制
通過表單重復(fù)發(fā)送數(shù)據(jù)是一個常見的情況,但是它會帶來問題。在理想的情況下,用戶在一個 Web
站點遇到一個表單,用正確的數(shù)據(jù)類型填充它,將它提交給處理數(shù)據(jù)的服務(wù)器,然后作為回應(yīng)發(fā)送給用戶一個確認(rèn)頁,這時用戶就可以再去做別的。如果用戶重新訪問前面那一頁,使用back
按鈕,然后無意中再將數(shù)據(jù)發(fā)送一次,那將會出現(xiàn)什么情形呢?如果你沒有預(yù)料到這一場景并且有所準(zhǔn)備,數(shù)據(jù)就將被重新傳送給服務(wù)器并且再處理一次。試想這些數(shù)據(jù)是一份訂單或旅館預(yù)約,那將會帶來很不愉快的結(jié)果。
終止重復(fù)數(shù)據(jù)傳輸
為了避免那些錯誤地重復(fù)發(fā)送給服務(wù)器的數(shù)據(jù),可以在服務(wù)器側(cè)進(jìn)行一些校驗,來確定用戶能
意識到他們正在發(fā)送數(shù)據(jù)。這里使用的例子包含一個有單一文本框的簡單表單,表單接收一些文本,然后將其發(fā)送到一個顯示它們的ASP頁。
為確保用戶不將同樣的信息發(fā)送兩次,需要指示數(shù)據(jù)已經(jīng)被服務(wù)器接收到。存儲這些信息的最好的地方是一個session變量。定義一個session變量Session("submitted")
,當(dāng)用戶第一次到達(dá)這個表單時將它初始化為False,在用戶進(jìn)行最初的數(shù)據(jù)傳輸時將它設(shè)置為true
。如果用戶在當(dāng)前的session期間重新訪問這個表單,將出現(xiàn)相關(guān)重復(fù)提交信息。
所以用戶只能是在有意的情況下向服務(wù)器重復(fù)發(fā)送數(shù)據(jù)?,F(xiàn)在來看看執(zhí)行這一校驗的代碼。建立表單并且校驗已發(fā)送數(shù)據(jù)的ASP頁(在下載處為form.asp)有以下結(jié)構(gòu):
〈 HTML 〉
〈 HEAD 〉
〈 /HEAD 〉
〈 BODY 〉
〈 % If
Session("submitted") Then % 〉
〈 !-- Code showing the warning message -- 〉
... 〈 % Else % 〉
〈 !-- Code showing the form -- 〉
... 〈 % End If % 〉
〈 /BODY 〉
〈 /HTML 〉
表單和警告信息都是從同一個ASP頁創(chuàng)建的。表單包括標(biāo)準(zhǔn)的HTML代碼,引用ManageForm.asp頁作為它的ACTION 屬性:
〈 FORM METHOD="post" ACTION="ManageForm.asp" 〉
Send me some data:
〈 INPUT TYPE="text" NAME="data" 〉
〈 P 〉
〈 INPUT TYPE="submit"
VALUE="Submit" 〉
〈 INPUT TYPE="reset" VALUE="Cancel" 〉
〈 /FORM 〉
ManageForm.asp 頁接收用戶發(fā)送的文本,顯示它并將session 變量submitted設(shè)置為True:
〈 HTML 〉
〈 HEAD 〉
〈 /HEAD 〉
〈 BODY 〉
You have sent the following
information:
〈 P 〉
〈 %= Request("data") % 〉
〈 % Session("submitted")
= True % 〉
〈 /BODY 〉
〈 /HTML 〉
所以當(dāng)用戶又回到這個表單時,測試session
變量submitted,當(dāng)它的值為True時,發(fā)送給用 戶的是警告信息而不是輸入表單。這個警告信息是用HTML和客戶機側(cè)的Javascript代碼組合編寫的:
〈 script 〉
function SendAnswer(answer) {
document.AnswerForm.answer.value = answer document.AnswerForm.submit() }
〈
/script 〉
You have already submitted some information to this Web site.
〈 BR 〉 Do you want submit again?
〈 P 〉
〈 FORM NAME="AnswerForm"
METHOD="post" ACTION="CheckAnswer.asp" 〉
〈 INPUT TYPE="button" VALUE="Yes"
onClick="SendAnswer('Y')" 〉
〈 INPUT TYPE="button" VALUE="No"
onClick="SendAnswer('N')" 〉
〈 INPUT TYPE="hidden" NAME="answer" VALUE="" 〉
〈 /FORM 〉
表單包含兩個按鈕((Yes 和 No) 以及一個隱含控制域(answer) ,在其中保存用戶所選擇的值: Y 或
N。這個值由Javascript 函數(shù)SendAnswer() 設(shè)置,這個函數(shù)還將它發(fā)送給CheckAnswer.asp
頁以執(zhí)行正確的重定向。如果用戶選擇了No按鈕,CheckAnswer.asp 檢驗隱含控制的值,并將其重定向到一個普通 welcome
頁,反之就將session 變量submitted設(shè)置為False 并再次將其重定向到表單頁。
〈 % If Request("answer") =
"Y" Then Session("submitted") = False Response.Redirect "form.asp" Else
Response.Redirect "welcome.htm" End If % 〉
控制瀏覽器緩沖器
如果你已經(jīng)實施了以上方法,你會發(fā)現(xiàn),只有當(dāng)你在瀏覽器的地址文本框內(nèi)鍵入URL來回到這個
表單時,此方法才奏效。它依靠的是瀏覽器的緩沖器機制。如果你使用back按鈕來返回頁,瀏覽器就檢測它的緩沖器來找到該頁的副本。它將使用緩存的頁而不是向服務(wù)器發(fā)出請求。所以服務(wù)器就
不能在session
變量submitted上進(jìn)行校驗。為了避免這種情況,就要抑制瀏覽器的頁緩沖器。這通過在表單頁中處理Response對象來實現(xiàn)。取消頁緩沖器有多種方法。所有這些方法都要依靠HTTP頭文件中到瀏覽器的地址指示。但是所有瀏覽器對服務(wù)器發(fā)送的指示反應(yīng)不同,所以說最好能多發(fā)送一些指示來為更多的瀏覽器抑制緩沖器,按以下代碼所示:
〈 % Response.AddHeader "cache-control", "private" Response.AddHeader
"pragma", "no-cache" Response.ExpiresAbsolute = #January 1, 1990 00:00:01#
Response.Expires=0 % 〉
以上代碼的頭兩行使用Response 對象的AddHeader
方法來將頭信息附加到HTTP頭文件中。 Expires 和 ExpiresAbsolute
屬性用瀏覽器緩沖器中頁的持續(xù)時間信息來標(biāo)記當(dāng)前頁。在表單頁中,這些行必須要插入在所有代碼之前,因為她們所引用的信息放置在HTTP頭文件中,在所有輸出之前發(fā)送給瀏覽器。
多步驟表單
如果一個表單需要許多數(shù)據(jù),那么最好將你要求的數(shù)據(jù)劃分成多個小表單,這樣使用戶可以一步一步地填充表單,而不用等待表單加載許多HTML控制。另外還有一些情況,表單中的某些控制不完全必要,并且可以用已經(jīng)提交的數(shù)據(jù)逐行填充。使用多步驟表單允許顯示倚賴于用戶以前答案的定制表單。如果用戶在瀏覽器中將一個中間表單設(shè)置為書簽的話就會產(chǎn)生問題。在隨后的一個session中,用戶就試圖直接到達(dá)這個表單并提交數(shù)據(jù),這些數(shù)據(jù)已經(jīng)在上下文范圍之外,因為本來應(yīng)該在前面
表單收集的session 數(shù)據(jù)丟失了。
避免使用中間步驟表單
為了避免這些問題,可以存儲當(dāng)前數(shù)據(jù)收集的狀態(tài)。這個狀態(tài)可以用一個session 變量來代表
來記錄是否執(zhí)行了一個特定的步驟---用戶是否填充了給出的表單。在一個多步驟表單中,每個表單都可以通過一個Boolean型的session變量來實現(xiàn)。如果有關(guān)表單沒有被處理,變量就為False
,反之就是True。下載部分的第二個例子顯示一個兩步驟表單:第一個表單要求用戶名,第二個表單顯示一個組合框,它的列表項要依賴第一個表單所提供的用戶名。第一個表單與一個session變量requested1相關(guān)聯(lián),你可以想象出來,第二個表單與變量requested2相關(guān)聯(lián)。當(dāng)用戶要求第一個表單(form1.asp)
時,session變量 requested1 被設(shè)置為 True :
〈 FORM METHOD="post"
ACTION="form2.asp" 〉
Your name: 〈 INPUT TYPE="text" NAME="name" 〉
〈 P 〉
〈 INPUT TYPE="submit" VALUE="Submit" 〉
〈 INPUT TYPE="reset"
VALUE="Cancel" 〉
〈 /FORM 〉
〈 % Session("requested1") = True % 〉
這個值將由下一個表單( form2.asp ) 來校驗,以確定是否滿足了要求。事實上當(dāng)用戶要求第二個表單時校驗requested1
變量。如果為True,就向瀏覽器發(fā)送第二個表單并將requested2變量設(shè)置為True。如果為False
就意味著用戶想要直接使用第二個表單,于是瀏覽器就重定向到第一個表單。以下代碼是第二個表單的ASP頁:
〈 % If
Session("requested1") Then % 〉
〈 HTML 〉
〈 HEAD 〉
〈 /HEAD 〉
〈
BODY 〉
〈 !-- Code for the second form -- 〉
... 〈 % Session("requested2")
= True Else Response.Redirect "form1.asp" End If % 〉
〈 /BODY 〉
〈 /HTML 〉
要注意對requested1 的校驗必須要在〈 HTML
〉記錄之前進(jìn)行,這樣就允許可能的重定向。實際上,重定向是對瀏覽器的指示,它出現(xiàn)在HTTP頭文件中,在所有的HTML代碼之前。
結(jié)論
本文所示范的兩種技巧允許ASP開發(fā)人員對某些奇怪的情況有所控制,這些奇怪情況會造成用戶 通過一個Web
表單向服務(wù)器重復(fù)發(fā)送數(shù)據(jù)。每個技巧解決一個特定問題,所以最好將兩者混合使用,在ASP應(yīng)用程序每個表單中管理兩個session 變量。[@more@]
標(biāo)題名稱:高級表單驗證-針對多次提交表單(轉(zhuǎn))
文章地址:http://jinyejixie.com/article4/gpejoe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、網(wǎng)站維護(hù)、用戶體驗、定制網(wǎng)站、搜索引擎優(yōu)化、虛擬主機
廣告
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源:
創(chuàng)新互聯(lián)