ViewState Session Static區別

CodeAgriculture發表於2013-03-26
Normal 0 0 2 false false false EN-US ZH-TW X-NONE一、ViewState與Static的區別:
在做BS模式的頁面時也用static變數,殊不知Asp.net中的static已不同於CS中的static。原因很簡單,就是因為在Asp.net中所有的使用者將使用同一個static變數。這就意味著每一個使用該頁面的使用者對該變數的操作將會影響到其他使用者。就拿上面計數器的例子來說,假設times初試值為0,因為此時只有我們自己在使用這個頁面,當然不會有什麼問題,但如果有兩個人同時連線到這個頁面,如果A單擊了Button1一次,則B重新整理頁面後Label1將顯示1,如果B再單擊Button1一次,則times變成2,兩個人重新整理頁面後就出現問題了:A和B都會說,我明明只單擊了Button1一次,怎麼Label1就顯示我單擊了兩次哪?——這就是因為兩個人共享的是伺服器上同一個times,任何一個人對times的操作都會在使用該頁面的他人的瀏覽器中表現出來。問題就出在這裡。
    怎麼辦哪?還好,除了傳統的Asp中的Session物件外,Asp.net提供了一個更好的ViewState物件。ViewState物件用來儲存頁面中的各種變數,甚至是物件。使用方法和HashTable類似,只要用變數名稱做索引,如ViewState["Var"],就可以用存取變數Var的值,而不管Var是普通變數,還是物件,甚至是記憶體中的一張DataTable,太方便了。為什麼可以用ViewState而不能用static變數哪?原因就是伺服器端會為每個連線到該頁面的使用者分別建立一個ViewState,所以ViewState相當於頁面級的Session。這下我們可以放心地使用ViewState來存取需要暫存的變數和物件了。
    ViewState的用法很簡單,如下所示:
    1、儲存變數到ViewState中:
       ViewState["times"]=times;//存放普通變數times
       ViewState["Orders"]=dtOrders;//存放DataTable型物件dtOrders
    2、讀出ViewState中的值:
       times=(int)ViewState["times"];
       dtOrders=(DataTable)ViewState["Orders"];
    看見了吧?就如此簡單!有的朋友會問讀出變數的值時為什麼要進行強制型別換?這是因為當變數(不管是int型的普通變數times,還是DataTable型的物件dtOrders)被存放到ViewState中後,ViewState可不管你是普通變數還是物件,統統按Object來對待。所以當我們取出存放在ViewState中的東西時,一定要換成相應的型別,否則就會報錯。而這一操作不用在用ViewState儲存變數時進行,系統會自動換。(注意ViewState括號中的字串只是為了標識不同變數的索引,用不著非要和變數同名)所以上面計數器的程式碼應該這樣寫才好:
       ...
       ViewState["times"]=0;
       ...
       private void Button1_Click(object sender,EventArgs e)
       {
           int times=(int)ViewState["times"];
           times++;
           ViewState["times"]=times;
           Label1.Text=times.ToString();
        }
    一般情況向下,將要儲存到ViewState中的物件(或變數)用屬性的形式來實現會更方便。如對於上述的計數器times,可以這樣處理:
    ...
    private int times
    {
        get
         {
            return (int)ViewState["times"];
         }
        set
        {
            ViewState["times"]=value;
        }
    }
    ...
    private void Button1_Click(object sender,EventArgs e)
     {
        times++;
        Label1.Text=times.ToString();
     }
    ...
    在這裡times將當作私有屬性來操作,是不是非常方便?
    那是不是說static型變數就沒用了哪?當然不是!在C#中用static宣告的類不用例項化直接使用。正是由於所有使用者共享伺服器端的同一個static變數,所以可以用static型物件來存取一些公用的處理模組,比如型別換、變數驗證等工作。所以要根據具體情況而定。
    還有一點需要注意:如果在頁面中多個過程要共享一個物件或變數,我們在頁面類的開始部分定義一個頁面級的全域性變數是不行的,static本來可以,但上面說了這種型別的變數不安全,所以這時就可以用ViewState
 二、ViewStateSession的區別
session值是儲存在伺服器記憶體上,那麼,可以肯定,大量的使用session將導致伺服器負擔加重. 而viewstate由於只是將資料存入到頁面隱藏控制元件裡,不再佔用伺服器資源,因此, 我們可以將一些需要伺服器"記住"的變數和物件儲存到viewstate裡面. 而sesson則只應該應用在需要跨頁面且與每個訪問使用者相關的變數和物件儲存上. 另外,session在預設情況下20分鐘就過期,而viewstate則永遠不會過期.

但viewstate並不是能儲存所有的.net型別資料,它僅僅支援String、Integer、Boolean、Array、ArrayList、Hashtable 以及自定義的一些型別.

當 然,任何事物都有兩面性, 使用viewstate會增加頁面html的輸出量,佔用更都的頻寬,這一點是需要我們慎重考慮的. 另外, 由於所有的viewstate都是儲存在一個隱藏域裡面,使用者可以很容易的透過檢視原始碼來看到這個經過base64編碼的值.然後再經過轉換就可以獲取你 儲存其中的物件和變數值.

其實,對於viewstate的安全性問 題,asp.net還給我們提供了更多的選擇.一般如果要保護viewstate有兩種方式: 一種是防篡改,一種是加密. 一說到防篡改,我們就想起了使用雜湊程式碼. 沒錯, 我們可以在頁面頂部加入如下程式碼:Page EnableViewStateMAC=true

這 樣asp.net就會自動的在viewstate中追加一個雜湊碼,在頁面回傳時,伺服器根據回傳的viewstate生成一個雜湊碼,再與回傳的雜湊碼 相比較,如果不對,則丟棄該viewstate,同時控制元件將恢復初試狀態. (預設情況下asp.net是透過SHA1演算法而不是md5演算法來生成雜湊,不過這個可以在machine.config裡面配置machineKey validation="MD5"即可)

而viewstate加密就更簡單了, 只要在machine.config裡設定一下machineKey validation="3DES"即可實現用des加密viewstate了.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28699126/viewspace-757171/,如需轉載,請註明出處,否則將追究法律責任。

相關文章