進階表單驗證-針對多次提交表單

來源:互聯網
上載者:User
表單驗證|進階|提交表單   每個開發人員面對的困難是預測使用者能夠或是將要做什麼--這對於網路開發人員來說就更為困 難,因為他的預測必須考慮到Web 的多樣性和缺乏真正的session控制機制。如果你已經建立過一個使用表單的ASP應用程式,也許你已經遇到過一些奇怪的問題,如資料轉送兩次,接收資料不完整,或者使用者報告表單顯示不正確。儘管你也插入了確認資料所需的所有客戶機端和伺服器端的指令碼,表單仍然會發生許多異常情況。這些異常情況與意外使用者行為或瀏覽器書籤的誤使用有關。本文將集中解決一些容易引起表單問題的典型情況:使用者意外地重複發送資料,在多步驟表單中直接使用中間表單。

資料複製

  通過表單重複發送資料是一個常見的情況,但是它會帶來問題。在理想的情況下,使用者在一個 Web 網站遇到一個表單,用正確的資料類型填充它,將它提交給處理資料的伺服器,然後作為回應發送給使用者一個確認頁,這時使用者就可以再去做別的。如果使用者重新訪問前面那一頁,使用back 按鈕,然後無意中再將資料發送一次,那將會出現什麼情形呢?如果你沒有預料到這一情境並且有所準備,資料就將被重新傳送給伺服器並且再處理一次。試想這些資料是一份訂單或旅館預約,那將會帶來很不愉快的結果。

終止重複資料轉送

  為了避免那些錯誤地重複發送給伺服器的資料,可以在伺服器側進行一些校正,來確定使用者能 意識到他們正在發送資料。這裡使用的例子包含一個有單一文字框的簡單表單,表單接收一些文本,然後將其發送到一個顯示它們的ASP頁。 為確保使用者不將同樣的資訊發送兩次,需要指示資料已經被伺服器接收到。儲存這些資訊的最好的地方是一個session變數。定義一個session變數Session("submitted") ,當使用者第一次到達這個表單時將它初始化為False,在使用者進行最初的資料轉送時將它設定為true 。如果使用者在當前的session期間重新訪問這個表單,將出現相關重複提交資訊。
所以使用者只能是在有意的情況下向伺服器重複發送資料。現在來看看執行這一校正的代碼。建立表單並且校正已發送資料的ASP頁(在下載處為form.asp)有以下結構:
〈 HTML 〉
〈 HEAD 〉
〈 /HEAD 〉
〈 BODY 〉
〈 % If Session("submitted") Then % 〉
〈 !-- Code showing the warning message -- 〉
... 〈 % Else % 〉
〈 !-- Code showing the form -- 〉
... 〈 % End If % 〉
〈 /BODY 〉
〈 /HTML 〉

  表單和警告資訊都是從同一個ASP頁建立的。表單包括標準的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 頁接收使用者發送的文本,顯示它並將session 變數submitted設定為True:
〈 HTML 〉
〈 HEAD 〉
〈 /HEAD 〉
〈 BODY 〉
You have sent the following information:
〈 P 〉
〈 %= Request("data") % 〉
〈 % Session("submitted") = True % 〉
〈 /BODY 〉
〈 /HTML 〉

  所以當使用者又回到這個表單時,測試session 變數submitted,當它的值為True時,發送給用 戶的是警告資訊而不是輸入表單。這個警告資訊是用HTML和客戶機側的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" 〉
〈 INPUT TYPE="button" VALUE="No" 〉
〈 INPUT TYPE="hidden" NAME="answer" VALUE="" 〉
〈 /FORM 〉

  表單包含兩個按鈕((Yes 和 No) 以及一個隱含控制域(answer) ,在其中儲存使用者所選擇的值: Y 或 N。這個值由JavaScript 函數SendAnswer() 設定,這個函數還將它發送給CheckAnswer.asp 頁以執行正確的重新導向。如果使用者選擇了No按鈕,CheckAnswer.asp 檢驗隱含控制的值,並將其重新導向到一個普通 welcome 頁,反之就將session 變數submitted設定為False 並再次將其重新導向到表單頁。
〈 % If Request("answer") = "Y" Then Session("submitted") = False Response.Redirect "form.asp" Else Response.Redirect "welcome.htm" End If % 〉

控制瀏覽器緩衝器

  如果你已經實施了以上方法,你會發現,只有當你在瀏覽器的地址文字框內鍵入URL來回到這個 表單時,此方法才奏效。它依靠的是瀏覽器的緩衝器機制。如果你使用back按鈕來返回頁,瀏覽器就檢測它的緩衝器來找到該頁的副本。它將使用緩衝的頁而不是向伺服器發出請求。所以伺服器就 不能在session 變數submitted上進行校正。為了避免這種情況,就要抑制瀏覽器的頁緩衝器。這通過在表單頁中處理Response對象來實現。取消頁緩衝器有多種方法。所有這些方法都要依靠HTTP標頭檔中到瀏覽器的地址指示。但是所有瀏覽器對伺服器發送的指示反應不同,所以說最好能多發送一些指示來為更多的瀏覽器抑制緩衝器,按以下代碼所示:

〈 % 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 屬性用瀏覽器緩衝器中頁的期間資訊來標記當前頁。在表單頁中,這些行必須要插入在所有代碼之前,因為她們所引用的資訊放置在HTTP標頭檔中,在所有輸出之前發送給瀏覽器。

多步驟表單

  如果一個表單需要許多資料,那麼最好將你要求的資料劃分成多個小表單,這樣使使用者可以一步一步地填充表單,而不用等待表單載入許多HTML控制。另外還有一些情況,表單中的某些控制不完全必要,並且可以用已經提交的資料逐行填充。使用多步驟表單允許顯示倚賴於使用者以前答案的定製表單。如果使用者在瀏覽器中將一個中間表單設定為書籤的話就會產生問題。在隨後的一個session中,使用者就試圖直接到達這個表單並提交資料,這些資料已經在上下文範圍之外,因為本來應該在前面 表單收集的session 資料丟失了。

避免使用中間步驟表單

  為了避免這些問題,可以儲存當前資料收集的狀態。這個狀態可以用一個session 變數來代表 來記錄是否執行了一個特定的步驟---使用者是否填充了給出的表單。在一個多步驟表單中,每個表單都可以通過一個Boolean型的session變數來實現。如果有關表單沒有被處理,變數就為False ,反之就是True。下載部分的第二個例子顯示一個兩步驟表單:第一個表單要求使用者名稱,第二個表單顯示一個組合框,它的清單項目要依賴第一個表單所提供的使用者名稱。第一個表單與一個session變數requested1相關聯,你可以想象出來,第二個表單與變數requested2相關聯。當使用者要求第一個表單(form1.asp) 時,session變數 requested1 被設定為 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 ) 來校正,以確定是否滿足了要求。事實上當使用者要求第二個表單時校正requested1 變數。如果為True,就向瀏覽器發送第二個表單並將requested2變數設定為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 〉記錄之前進行,這樣就允許可能的重新導向。實際上,重新導向是對瀏覽器的指示,它出現在HTTP標頭檔中,在所有的HTML代碼之前。

結論

  本文所示範的兩種技巧允許ASP開發人員對某些奇怪的情況有所控制,這些奇怪情況會造成使用者 通過一個Web 表單向伺服器重複發送資料。每個技巧解決一個特定問題,所以最好將兩者混合使用,在ASP應用程式每個表單中管理兩個session 變數。

相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。