ASP.NET伺服器控制項之檢視狀態

來源:互聯網
上載者:User
為Web頁面及其控制項保持狀態資訊是非常有必要的。然而,由於Web應用程式建立於HTTP協議的頂層,這是一個無狀態的協議,因此,保持狀態資訊則變得非常困難。為瞭解決這個問題,ASP.NET 2.0技術提供了多種解決方案,例如,利用Session、Cookie、檢視狀態、控制項狀態、隱藏欄位、查詢字串、個人化使用者配置(Profile)等等。對於利用ASP.NET 2.0技術建立伺服器控制項而言,保持狀態資訊也是非常重要的,其主要解決途徑是利用檢視狀態和控制項狀態。本文詳細講解了檢視狀態(ViewState)的基本知識,並通過典型應用介紹檢視狀態的應用方法。

   檢視狀態概述

  檢視狀態是一項非常重要的技術,它能使得頁面和頁面中的控制項在從伺服器到用戶端,再從用戶端返回的往返過程中保持狀態資訊。這樣就可以在Web這種無狀態的環境之上建立一個有狀態並持續執行的頁面效果。本節主要介紹有關檢視狀態的運行機制、應用方法、儲存的資料類型、效能和安全性、檢視狀態分塊(這是ASP.NET 2.0的新特性)和優缺點等內容。

  (1)運行機制

  檢視狀態的具體運行過程為:每當使用者請求某個.aspx頁面時,.NET架構首先把相關控制項的狀態資料序列化成一個字串,然後,將其做為名為__VIEWSTATE的隱藏欄位的Value值發送到用戶端。如果頁面是第一次被請求,那麼伺服器控制項也將是被第一次執行時,名為__VIEWSTATE的隱藏欄位中只包含控制項的預設資訊,通常為空白或者null。在隨後的回送事件中,ViewState中就儲存了伺服器控制項在前面回送中可用的屬性狀態。這樣伺服器控制項就可以監視在當前被處理的回送事件發生之前的狀態了。這些過程是由.NET架構負責的,對使用者來說是執行.aspx頁面就有了持續執行的效果。

  (2)儲存的資料類型

  檢視狀態可以儲存多種類型的資料,並且為了提高運行效率,檢視狀態自身還包括一套已經最佳化的針對常用類型的序列化方式。檢視狀態序列化方式預設支援的資料類型包括以下幾種:String、Int32、Unit、Color、Array、ArrayList、HashTable和自訂類型轉換器TypeConverter。

  檢視狀態已經為Array、ArrayList和包含上面列出類型的HashTable對象進行了最佳化。因此,當在控制項中使用檢視狀態時,應該試著限定於使用以上單一資料型別,以及經過最佳化的類型。在此,需要重點說明一下自訂類型轉換器TypeConverter,它提供了一種將值的類型轉換為其他類型以及訪問標準值和子屬性的統一方法。例如,可以利用TypeConverter將字串轉換為數值,或者將數值轉換為字串。如果沒有類型轉換器,那麼頁面架構會使用.NET架構提供的二進位序列化功能來序列化對象,這個過程是非常耗費資源的。

  (3)效能和安全性

  使用檢視狀態時,對象必須先序列化,然後再通過回傳進行還原序列化。因此,我們必須瞭解有關ViewState效能的內容。預設情況下,控制項的ViewState將被啟用,如果不需要使用ViewState,最好還是將它關閉。以下情況將不再需要ViewState:(1)控制項未定義伺服器端事件(這時的控制項事件均為用戶端事件且不參加回送的);(2)控制項沒有動態或資料繫結的屬性值。關閉檢視狀態的方法是將控制項的EnableViewState的值設定為"false",即EnableViewState="false"。

  預設情況下,檢視狀態的有關內容在編譯運行發送給用戶端時,讀者將在頁面的HTML代碼中看到__VIEWSTATE隱藏欄位內容。這是一些沒有意義的字串,是.NET架構通過Base64位編碼對相關內容編碼的結果。它們是通過明文方式在用戶端和伺服器端之間往返傳送。在某些情況下,例如涉及密碼、帳號、連接字串等敏感內容時,使用預設是很不安全的。為此,.NET架構為ViewState提供了兩種安全機制:

  · 校正機制:

  可以通過設定EnableViewStateMAC="true"屬性來指示.NET架構向ViewState資料中追加一個散列碼(該散列碼是一種SHA1類型,長度有160位,因此會嚴重影響執行效能)。在回傳事件發生時,將重建立立該散列碼,它必須和最初的散列碼匹配。通過這種方式,能夠有效檢驗ViewState是否在傳送過程中能夠被篡改。預設情況下,.NET架構使用SHA1演算法來產生ViewState散列代碼。此外,也可以通過在machine.config檔案中設定<machineKey>來選擇 MD5 演算法,如下所示:<machineKey validation="MD5" />。MD5演算法的效能要比SHA1演算法好一些,但是同樣不夠安全。

  · 加密機制

  使用加密來保護ViewState欄位中的實際資料值。首先,必須如上所述設定EnableViewStatMAC="true"。然後,將machineKey validation類型設定為3DES,即<machineKey validationKey="AutoGenerate" decryptionKey="AutoGenerate" validation="3DES" />,這指示ASP.NET使用3DES密碼編譯演算法來加密ViewState值。

  (4)檢視狀態分塊

  以上內容介紹了檢視狀態的一些基本知識。然而,可能部分讀者會有些疑惑:如果在某些情況下,檢視狀態資料變得很大,那怎麼辦呢?這樣顯然會出現一些意想不到的後果。為此,ASP.NET 2.0新增了一種名為"檢視狀態分塊"的功能。如果檢視狀態的資料量變得太大,檢視狀態分塊自動將資料分成多個塊區,並將這些資料放在多個隱藏形式的欄位中。

  若要啟用檢視狀態分塊,可將MaxPageStateFieldLength屬性設定為在單個檢視狀態欄位中允許的最大大小(以位元組為單位)。當該頁回傳到伺服器時,該頁會在頁初始化階段分析檢視狀態字串,並還原頁中的屬性資訊。預設設定是-1,這表示不存在最大大小,不會將檢視狀態分成多個塊區。

  (5)優點和缺點

  使用檢視狀態具有以下3個優點:一、耗費的伺服器資源較少(與Application、Session相比)。因為,檢視狀態資料都寫入了用戶端電腦中。二、易於維護。預設情況下,.NET系統自動啟用對控制項狀態資料的維護。三、增強安全功能。檢視狀態中的值經過雜湊計算和壓縮,並且針對Unicode實現進行編碼,其安全性要高於使用隱藏欄位。

  使用檢視狀態具有以下3個缺點:一、效能注意事項。由於檢視狀態儲存在頁本身,因此如果儲存較大的值,即使在檢視狀態分塊的情況下,使用者顯示頁和發送頁時的速度仍然可能減慢。二、裝置限制。行動裝置可能沒有足夠的記憶體容量來儲存大量的檢視狀態資料。因此,行動裝置上的伺服器控制項時,將使用其他的實現方法。三、潛在的安全風險。檢視狀態儲存在頁上的一個或多個隱藏欄位中。雖然檢視狀態以雜湊格式儲存資料,但它可以被篡改。如果直接查看頁輸出源,可以看到隱藏欄位中的資訊,這導致潛在的安全性問題。

典型應用

  在利用ASP.NET 2.0技術進行伺服器控制項開發過程中,有很多方面可以用到檢視狀態。常見的是利用ViewState字典實現伺服器控制項屬性。ViewState是System.Web.UI.StateBag類型-一個鍵/值對的字典,伺服器控制項的屬性值可以儲存在ViewState中。下面通過一個典型樣本,說明ViewState的應用方法。

  在自訂伺服器控制項LabelInViewState中,實現了兩個屬性Text和TextInViewState。前者使用私人變數建立,後者使用ViewState實現。它們都用於擷取或者設定常值內容。自訂控制項實現檔案LabelInViewState.cs原始碼如下所示。

using System;using System.Collections.Generic;
using System.ComponentModel;using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;namespace WebControlLibrary{
 [DefaultProperty("Text")]
 [ToolboxData("<{0}:LabelInViewState runat=server></{0}:LabelInViewState>")]
 public class LabelInViewState : WebControl {
  private string _text; //實現Text屬性
  public string Text {
   get {
    return (_text == null) ? string.Empty : _text;
   }
   set { _text = value; }
  }
  //使用ViewState實現TextInViewState屬性
  public string TextInViewState {
   get {
    String s = (String)ViewState["TextInViewState"];
    return ((s == null) ? String.Empty : s);
   }
   set { ViewState["TextInViewState"] = value; }
  }
  // 重寫RenderContents方法
  protected override void RenderContents(HtmlTextWriter output) {
   output.Write("Text = ");
   output.Write(Text);
   output.Write("<br/>");
   output.Write("TextInViewState = ");
   output.Write(TextInViewState);
  }
 }
}

  如上代碼所示,控制項實現了兩個屬性Text和TextInViewState。Text屬性使用了私人變數_text建立,這種實現無法保持該屬性的狀態資訊。TextInViewState屬性使用了ViewState,其通過set訪問器,將屬性值寫入ViewState["TextInViewState"]對象中,通過get訪問器,從對象ViewState["TextInViewState "]中擷取屬性值。這就是檢視狀態處理最簡單的方法。當使用ViewState作為屬性儲存區時,自訂伺服器控制項可以自行完成簡單的狀態資訊管理,例如,TrackViewState、SaveViewState、LoadViewState等。當然,開發人員也可以通過重寫方法自訂狀態管理邏輯程式。在本例中,檢視狀態管理過程都是由.NET架構自動完成的。

  下面列舉了為測試以上自訂伺服器控制項而建立的Default.aspx檔案原始碼。

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Namespace="WebControlLibrary" Assembly="WebControlLibrary" TagPrefix="sample" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 void Button1_Click(object sender, EventArgs e) {
   demoLabel.Text = TextBox1.Text;
   demoLabel.TextInViewState = TextBox2.Text;
 }
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>使用檢視狀態ViewState</title>
</head>
<body style="font-size: small;">
<form id="form1" runat="server"> <div> 姓名:

  以上代碼顯示在頁面中包括兩個文字框,兩個按鈕,以及一個自訂伺服器控制項LabelInViewState。如事件處理常式Button1_Click所示,當單擊"提交"按鈕時,LabelInViewState控制項將擷取文字框中文本,並顯示出來。應用程式效果圖如圖1和圖2所示。


圖1 單擊提交按鈕

圖2 單擊重載按鈕

  如圖1所示,當使用者在兩個文字框中填寫了文本,並單擊"提交"按鈕引發頁面回傳。此時,填寫的常值內容將提交到伺服器,並參與Button1_Click事件處理常式。這樣,LabelInViewState控制項則顯示出了Text和TextInViewState屬性值。之後,當使用者單擊"重載"按鈕時,文字框內容仍然提交到伺服器,但是,由於沒有對應的事件處理常式,因此,LabelInViewState控制項只顯示已經存在的狀態資訊(即單擊提交按鈕之後儲存的狀態),即Text屬性值為空白,而TextInViewState屬性值為tom@tom.com。通過以上過程可知,TextInViewState屬性值都儲存在檢視狀態ViewState中,因此,在頁面往返過程中,該屬性值得以保持,而Text只簡單使用了私人變數,所以狀態資訊無法保持。另外,需要注意的是,由於預設情況下,頁面啟用了檢視狀態EnableViewState = "true",才能實現以上效果。

   小結

  本文主要介紹了檢視狀態的基本概念,並通過一個典型樣本說明了應用方法。可能部分讀者已經認識到,如果禁用了頁面或者控制項的檢視狀態,即設定EnableViewState = "false",那麼上文伺服器控制項的屬性TextViewState不是不能使用了嗎?這的確是檢視狀態的缺陷所在。然而,這並不是說就無法解決這個問題了。在下文中,筆者將介紹另外一種ASP.NET 2.0新增的,與檢視狀態極為類似的技術特性--控制項狀態--它就能夠很好的解決禁用檢視狀態的問題。


相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。