大家都知道Web應用程式的無狀態,一個用戶端的請求,在其請求完成後,伺服器端都會刪除這個請求的相關資訊。有時我們需要Web請求完成後,還要繼續保持資訊,在傳統的Web編程中最常用的有兩種方式:Session、Cookies,但是這兩種傳統的方式,都有其弊端,Session會增加伺服器的負擔,Cookies則會依賴用戶端,要求用戶端必須支援Cookies,同時Cookies是存在用戶端的電腦上,所以可能有安全問題。
在Asp.net裡ms提出了一種新的狀態保持,這就是ViewState,當然原來的Session和Cookies在Asp.net可以繼續使用,那我們用一個Web的請求來說明一下ViewState的一個工作流程(只關心ViewState),即使不寫asp.net伺服器控制項,但我想瞭解一下頁面的請求和回傳對寫asp.net的程式還是很有好處的。
用戶端向服務端請求一個新的aspx頁面:
1、 伺服器端會建立一個控制項樹,再建立頁面上的所有控制項,把控制項加到控制項樹中。
2、 TrackViewState狀態跟蹤,檢查控制項的EnableViewState屬性,對EnableViewState=ture的控制項進行跟蹤。
3、 觸發頁面OnLoad。
4、 預產生OnPreRender。
5、 檢查控制項的EnableViewState屬性,對需要儲存狀態的調用SaveViewState[狀態1]。
6、 Render產生。
7、 … …
從用戶端回傳一個aspx頁面,頁面被Post回服務端後。
A、 和上述1一樣。
B、 和上述2一樣。
C、 LoadViewState,載入控制項提交前的狀態[就是載入狀態1]。
D、 LoadPostdata,從Post回來的表單中取出相應的資料,並把這些資料更新控制項的狀態[狀態2]。
E、 和上述3一樣。
F、 觸發修改事件和回傳事件。
G、 和上述4一樣。
H、 儲存狀態SaveViewState[狀態2]。
I、 Render。
J、 … …
上面就是ViewState的工作的一個流程,其實也就是aspx的生命週期,雖然我們在5和H對ViewState進行儲存,在C進行了ViewState的裝載,那又究竟是怎樣儲存和裝載的呢?這就是ViewState的序列化和並行化的,在5和H對ViewState進行序列化,把這些狀態序列化為一個字串(如value="/wEPDwULLTE3NjgxMzM0MDIPZBYCZg9kFgICBg9kFgICAQ9kFhACAQ8PFgQeC05hdmlnYXRlVXJsBRdodHRwOi8vd3d3LmNuYmxvZ3MuY29tLx4EVGV4dAUJ5Y2a5a6i5ZutZGQCAw8PFgIfAAUdaHR0cDovL21hcHNlcnZlci5jbmJsb2dzLmNvbS9kZAIHDw8WBh4GVGFyZ2V0ZR8ABR1odHRwOi8vbWFwc2VydmVyLmNuYmxvZ3MuY29tLx8BBQltYXBzZXJ2ZXJkZAIJDw8WBB8ABRdodHRwOi8vd3d3LmNuYmxvZ3MuY29tLx4ISW1hZ2VVcmwFFn4vSW1hZ2VzL2FkbWlubG9nby5naWZkZAINDxYCHgdWaXNpYmxlZ2QCHQ9kFgICAQ9kFgQCAg8PFgIeC0N")發送到用戶端,當頁面再被Post回服務端的時候,在C又對這個字串進行並行化,把它們還原序列化為對象狀態。aspx頁面有序列化和並行化的過程,同時這兩個過程的代價又是比較高昂的,所有我的原則是儘可能少的儲存控制項的ViewState。那什麼樣的對象可以被儲存在ViewState中呢?原則上來講,可以被序列化的對象都可以被儲存在ViewState中,但是在asp.net中ViewState對Array、ArrayList和HashTable進行了最佳化。
在aspx頁面的請求和回傳過程中ViewState都是以明文形式傳送,很容易被他人截取,對特別重要的資訊可以考慮加密或者用Session等方式來儲存,但這不是控制項開發人員的負責的,而應該是由頁面開發人員來完成。
最後:為什麼我們需要回傳的一個aspx頁面都必須有一個運行Runat=”Server”的Form的,上述的D中我們看出,我們需要這個Form來回傳控制項的更新資料。同時我們也可以看到所有的ViewState的處理都是服務端進行的,與用戶端沒有任何的關係,所有不管你是ie的用戶端還是firefox的用戶端,都可以訪問發布的asp.net網站。
如果在本文中發現有什麼不妥的地方,請朋友們給與指點,小弟在此先謝過。