只有累積,沒有奇蹟

2018年9月25日 星期二

[.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


0 意見:

張貼留言

Copyright © m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com