[.NET] ASP.NET 狀態管理(State Management):ViewState

Web應用程式是沒有狀態(Stateless)的,從前面介紹的文章(Application、Page Life-Cycle)可以了解到,每次用戶端發送請求(Request)到伺服器端時,都會建立Web網頁類別的新執行個體。由於每個請求都是新的個體,這也代表每次來回存取時,網頁及控制項的資訊將會遺失。例如,根據預設,當使用者在網頁textbox控制項輸入「Hello world」,按下按鈕送出後,這項資訊就會傳送到伺服器。但伺服器在回傳(Response)時,卻不會將此資訊「Hello world」回傳到瀏覽器。接下來要分享的有關ViewState使用方式

前言

    Web應用程式是沒有狀態(Stateless)的,從前面介紹的文章(ApplicationPage Life-Cycle)可以了解到,每次用戶端發送請求(Request)到伺服器端時,都會建立Web網頁類別的新執行個體。由於每個請求都是新的個體,這也代表每次來回存取時,網頁及控制項的資訊將會遺失。例如,根據預設,當使用者在網頁textbox控制項輸入「Hello world」,按下按鈕送出後,這項資訊就會傳送到伺服器。但伺服器在回傳(Response)時,卻不會將此資訊「Hello world」回傳到瀏覽器。(廢話好像越來越多了…還是快點進入主題好了 XD)
 

ASP.NET 狀態管理

    ASP.NET為了解決此問題,ASP.NET 網頁架構提供多種狀態管理(State Management)機制,提供開發者保留來回存取(Postback)Web伺服器之間網頁與控制項的值,如下圖所示

ASP.NET State Management

用戶端

  • View state(檢視狀態)
  • Control state(控制項狀態)
  • Hidden fields(隱藏欄位)
  • Cookies
  • Query strings(查詢字串)

伺服器端

  • Application state(應用程式狀態)
  • Session state(工作階段狀態)
  • Profile Properties(設定檔屬性)

每個狀態使用方式、優缺點都不相同,詳細請參考ASP.NET 狀態管理概觀
 

ViewState是什麼?

    ViewState是儲存於用戶端(Client-Base)的狀態管理機制,用來保存來回存取(Postback)之間的網頁和控制項的值,根據預設(EnableViewState=true),當ASP.NET執行網頁時,會收集網頁和所有控制項中的值並透過單一編碼(Base64)的字串,存放於隱藏表單欄位(hidden field)的值(Value)屬性中,由於隱藏表單欄位是傳送至使用者端網頁的一部分,所有ViewState值會暫時存放在用戶端的瀏覽器中。當網頁執行完之後,在網頁上滑鼠點右鍵,查看網頁原始檔可以看到類似下面的資訊

ViewStateSample

    從上圖可以得知,存放在隱藏欄位的值是透過Base64編碼後的字串,使用Base64編碼的原因有兩項,第一 :Base64編碼後的字串方便Http傳輸,第二:讓它不容易閱讀
註:但可以透過工具來解析

另外,使用ViewState前需先注意,ASP.NET 網頁中必須要有伺服器表單<form runat=”server”>,伺服器執行網頁值,ASP.NET網頁架構才能讀取/儲存隱藏欄位ViewState資訊,否則ViewState將無法正常運作。
 

Viewstate In Life Cycle

    在網頁生命週期中 ,有兩個事件跟ViewState有關係的,分別是LoadViewState、SaveViewstate,可以參考下圖所示

ViewState

LoadViewState:讀取隱藏表單欄位(hidden field)的值,將讀到的ViewState字串解碼,透過LoadPageStateFromPersistenceMedium方法還原檢視的狀態

SaveViewState:在PreRenderComplete事件之後,此事件會收集網頁及網頁上的控制項狀態(值)的資訊,將收集好的值透過Base64編碼成字串,透過SavePageStateToPersistenceMedium()方法,存放在ID為「__VIEWSTATE」隱藏表單欄位(hidden field)的值中。

註:以上兩個階段只會發生在當網頁觸發Postback後,如果有需要的話,這兩個方法都可以被覆寫。

ViewState使用方式

    使用方式很簡單,是採用鍵(key)與值(value)的方式儲存/讀取,用法如下


// set
ViewState["Text"] = "123";

// get
string myValue = ViewState["Text"].ToString();

    Viewstate預設為啟用,由控制項來決定所需要存入的ViewState物件。但是有時候這類資訊對於應用程式毫無用處。當網頁上的控制項資料很多的時候(如GridView),網頁的ViewState大小也會跟著增加,會造成傳輸網頁受到影響,這時候就必須考慮是否真的需要使用ViewState,或者可以直接停用ViewState功能。

停用Viewstate的方式有三種,可以透過設定控制項、網頁、設定檔三種層級屬性 EnableViewState為false

控制項(Control)的ViewState


<asp:Label id=Label1 runat="server" EnableViewState="false" />

網頁(Page)的ViewState


<%@ Page ... EnableViewState="false" %>

設定檔(WebConfig)的ViewState


<pages enableViewState="false" />

 

Session還是ViewState

    有時候會發現,使用ViewState 並不是最好得選擇。最常使用的替代方案為Session,ViewState不適用於

  • 呈現大量資料:ViewState會增加網頁傳送至瀏覽器的大小(HTML負載)和表單大小,儲存、呈現大量資料時不適用。
  • 安全性的資料:雖然ViewState是經過編碼並可以選擇性加密,但若不將資料傳送至用戶端還是最安全的。
  • ViewState不支援的物件(類型):如GridView,ViewState支援序列化的物件(註1)可以存於ViewState,但不支援的物件產生很大的ViewState且速度較慢。

Session與ViewState的比較,請參考下圖

VS

註1:ViewState支援: 字串, 整數, 布林, 陣列, 陣列清單, 雜湊資料表, 自訂 TypeConverter (strings, integers, Booleans, arrays, ArrayList, hashtable, custom TypeConverters)

資料來源:aspnetresources.com
 

補充

有關ViewState還有很多有相關的資訊,我先將他列出來,提供有興趣的朋友可以研究

參考

    此篇文章是上網查詢自己整理的結果,如果內容有錯誤的地方,麻煩各位高手給予小弟指導

如果覺得此篇文章不錯,請幫忙點選「我要推薦」;讓我有持續努力的動力,謝謝 :D

Understanding ASP.NET View State

ASP.NET Client Side State Management – ViewState

ViewState: Various ways to reduce performance overhead

ASP.NET Internals: Viewstate and Page Life Cycle

ViewState的運用

在 ASP.NET ViewState 中尋寶

ViewStateas Stage Management