Post/Redirect/Get pattern

今天重新認識了Post/Redirect/Get pattern, 感謝hip-hop的session, 一下幫助我理清了概念和思路.

 

談到pattern,首先要清楚它爲了什麼而產生: PRG (參見鏈接1)是爲了解決web頁面的double submit問題而提供的一種方案.

 

1. double submit problem

 

上下文: 用戶在browser中的pageA頁面完成輸入,點擊了提交按鈕,進入pageB頁面,提示"提交成功". 這時, 若分別出現下列三種case:

    1> 重新載入或刷新pageB;

    2> 點擊瀏覽器的後退按鈕,接着點擊前進按鈕;

    3> 點擊瀏覽器的後退按鈕退回到pageA,再點一回提交按鈕;

對於沒有考慮過這種問題而直接開發的網站,會出現什麼情況呢?

 

case 1和case 2會由瀏覽器彈出一個小窗口,提示大意如"可能重複提交頁面,是否繼續?"的詢問,如果選擇了yes,那麼前面的提交行爲會再做一次;而case 3屬於你主動地再一次提交. 也就是說,如果是買東西的話,那你已經重複買到了第二份! 這就是所謂的double submit.

 

究起實質, 是由於submit pageA和點擊提交按鈕共用了同一個服務器請求, 而這恰恰是一個POST請求, 在頁面被重複提交的背後, POST請求也被多次發送, 導致server上錯誤地多次執行了添加或更改數據的行爲. 圖1解釋了double submit問題.

DoubleSubmitProblem.png

                                                                圖 1 Double Submit Problem

2. PRG solusion

 

應該想到,用戶的這類如"後退再前進"或刷新的行爲, 應當視爲對歷史結果或頁面的查看, 並無再次提交之意.

 

解決問題的一種思路就是將用戶點擊提交按鈕從而發出POST請求, 頁面提交跳轉和顯示結果頁面這三個行爲分離開. PRG正是遵循這種思路, Client用POST方法請求Server響應數據變更, Server用Redirect方法將response指定到另一個URL上的結果頁面, Client所有對頁面顯示的請求都用GET方法告知Server. 解決方案如圖2所示. 這樣, "後退再前進"或刷新頁面的行爲都發出的是GET請求, 從而不會對server產生任何數據更改的影響, double submit problem得以解決.

DoubleSubmitSolution.png

                                                                   圖2  PRG solusion

 

Basic principles:

* 不要用一個頁面直接作爲POST請求的響應結果, 你會給習慣"後退再前進"的人留下resubmit難題.

* 在處理完POST請求之後, redirect到另一個URL頁面, 刷新頁面的人就只能看到它.

* 用GET而不是POST去請求一個頁面的顯示, 當你需要的僅僅是顯示的結果.

 

請注意:

* 後退到頁面內再點擊提交按鈕來提交頁面的行爲,依然被認爲是用戶自願的提交.

* 第一次提交後, Server的response正常完成之前的再次提交若未被所應用的框架阻止的話, 它會被Server認爲是另一個正常提交.

 

 

3. IsPostBack

 

值得一提的是, .Net WebForm中, 常在Page_Load方法中使用Page.IsPostBack屬性來判斷對當前Form的請求是第一次or非第一次, 這和本文討論的問題不完全一致: Asp.net提供了支持服務器端事件的控件, 同時還支持控件的AutoPostBack行爲, 故會多次發出對當前Form的請求, 而IsPostBack提供了加載頁面時的一個邏輯分支. IsPostBack屬性在多種情況下的取值規則可參見鏈接2 .

 

附參考鏈接:

[1]  http://en.wikipedia.org/wiki/Post/Redirect/Get

[2]  http://www.cnblogs.com/hobe/archive/2008/04/06/1139031.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章