熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

ASP.NET服務器控件之視圖狀態

2013-11-13 10:25:01  來源: .NET編程 

  為Web頁面及其控件保持狀態信息是非常有必要的然而由於Web應用程序創建於HTTP協議的頂層這是一個無狀態的協議因此保持狀態信息則變得非常困難為了解決這個問題 技術提供了多種解決方案例如利用SessionCookie視圖狀態控件狀態隱藏域查詢字符串個性化用戶配置(Profile)等等對於利用ASPNET 技術創建服務器控件而言保持狀態信息也是非常重要的其主要解決途徑是利用視圖狀態和控件狀態本文詳細講解了視圖狀態(ViewState)的基本知識並通過典型應用介紹視圖狀態的應用方法

  視圖狀態概述

  視圖狀態是一項非常重要的技術它能使得頁面和頁面中的控件在從服務器到客戶端再從客戶端返回的往返過程中保持狀態信息這樣就可以在Web這種無狀態的環境之上創建一個有狀態並持續執行的頁面效果本節主要介紹有關視圖狀態的運行機制應用方法存儲的數據類型性能和安全性視圖狀態分塊(這是 ASPNET 的新特性)和優缺點等內容

  ()運行機制

  視圖狀態的具體運行過程為每當用戶請求某個aspx頁面時NET框架首先把相關控件的狀態數據序列化成一個字符串然後將其做為名為__VIEWSTATE的隱藏域的Value值發送到客戶端如果頁面是第一次被請求那麼服務器控件也將是被第一次執行時名為__VIEWSTATE的隱藏域中只包含控件的默認信息通常為空或者 null在隨後的回送事件中ViewState中就保存了服務器控件在前面回送中可用的屬性狀態這樣服務器控件就可以監視在當前被處理的回送事件發生之前的狀態了這些過程是由NET框架負責的對用戶來說是執行aspx頁面就有了持續執行的效果

  ()存儲的數據類型

  視圖狀態可以存儲多種類型的數據並且為了提高運行效率視圖狀態自身還包括一套已經優化的針對常用類型的序列化方式視圖狀態序列化方式默認支持的數據類型包括以下幾種StringIntUnitColorArrayArrayListHashTable和自定義類型轉換器 TypeConverter

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

  ()性能和安全性

  使用視圖狀態時對象必須先序列化然後再通過回傳進行反序列化因此我們必須了解有關ViewState性能的內容默認情況下控件的ViewState將被啟用如果不需要使用ViewState最好還是將它關閉以下情況將不再需要ViewState)控件未定義服務器端事件(這時的控件事件均為客戶端事件且不參加回送的))控件沒有動態的或數據綁定的屬性值關閉視圖狀態的方法是將控件的EnableViewState的值設置為false即EnableViewState=false

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

  · 校驗機制

  可以通過設置EnableViewStateMAC=true屬性來指示NET框架向ViewState數據中追加一個散列碼(該散列碼是一種 SHA類型長度有因此會嚴重影響執行性能)在回傳事件發生時將重新建立該散列碼它必須和最初的散列碼匹配通過這種方式能夠有效檢驗ViewState是否在傳送過程中能夠被篡改默認情況下NET框架使用SHA算法來生成ViewState散列代碼此外也可以通過在 nfig文件中設置<machineKey>來選擇 MD 算法如下所示<machineKey validation=MD />MD算法的性能要比SHA算法好一些但是同樣不夠安全

  · 加密機制

  使用加密來保護ViewState字段中的實際數據值首先必須如上所述設置EnableViewStatMAC=true然後將 machineKey validation類型設置為DES即<machineKey validationKey=AutoGenerate decryptionKey=AutoGenerate validation=DES />這指示ASPNET使用DES加密算法來加密ViewState值

  ()視圖狀態分塊

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

  若要啟用視圖狀態分塊可將MaxPageStateFieldLength屬性設置為在單個視圖狀態字段中允許的最大大小(以字節為單位)當該頁回發到服務器時該頁會在頁初始化階段分析視圖狀態字符串並還原頁中的屬性信息默認設置是這表示不存在最大大小不會將視圖狀態分成多個塊區

  ()優點和缺點

  使用視圖狀態具有以下個優點耗費的服務器資源較少(與 ApplicationSession相比)因為視圖狀態數據都寫入了客戶端計算機中易於維護默認情況下NET系統自動啟用對控件狀態數據的維護增強的安全功能視圖狀態中的值經過哈希計算和壓縮並且針對Unicode實現進行編碼其安全性要高於使用隱藏域

  使用視圖狀態具有以下個缺點性能注意事項由於視圖狀態存儲在頁本身因此如果存儲較大的值即使在視圖狀態分塊的情況下用戶顯示頁和發送頁時的速度仍然可能減慢設備限制移動設備可能沒有足夠的內存容量來存儲大量的視圖狀態數據因此移動設備上的服務器控件時將使用其他的實現方法潛在的安全風險視圖狀態存儲在頁上的一個或多個隱藏域中雖然視圖狀態以哈希格式存儲數據但它可以被篡改如果直接查看頁輸出源可以看到隱藏域中的信息這導致潛在的安全性問題

  在利用 技術進行服務器控件開發過程中有很多方面可以用到視圖狀態常見的是利用ViewState字典實現服務器控件屬性ViewState是SystemWebUIStateBag類型一個鍵/值對的字典服務器控件的屬性值可以存儲在ViewState中下面通過一個典型示例說明ViewState的應用方法

  在自定義服務器控件LabelInViewState中實現了兩個屬性Text和TextInViewState前者使用私有變量創建後者使用 ViewState實現它們都用於獲取或者設置文本內容自定義控件實現文件LabelInViewStatecs源代碼如下所示

using System;using SystemCollectionsGeneric;
using SystemComponentModel;using SystemText;
using SystemWeb;
using SystemWebUI;
using SystemWebUIWebControls;namespace WebControlLibrary{
 [DefaultProperty(Text)]
 [ToolboxData(<{}:LabelInViewState runat=server></{}:LabelInViewState>)]
 public class LabelInViewState : WebControl {
  private string _text; //實現Text屬性
  public string Text {
   get {
    return (_text == null) ? stringEmpty : _text;
   }
   set { _text = value; }
  }
  //使用ViewState實現TextInViewState屬性
  public string TextInViewState {
   get {
    String s = (String)ViewState[TextInViewState];
    return ((s == null) ? StringEmpty : s);
   }
   set { ViewState[TextInViewState] = value; }
  }
  // 重寫RenderContents方法
  protected override void RenderContents(HtmlTextWriter output) {
   outputWrite(Text = );
   outputWrite(Text);
   outputWrite(<br/>);
   outputWrite(TextInViewState = );
   outputWrite(TextInViewState);
  }
 }
}

  如上代碼所示控件實現了兩個屬性Text和TextInViewStateText屬性使用了私有變量_text創建這種實現無法保持該屬性的狀態信息TextInViewState屬性使用了ViewState其通過set訪問器將屬性值寫入ViewState [TextInViewState]對象中通過get訪問器從對象ViewState[TextInViewState ]中獲取屬性值這就是視圖狀態處理最簡單的方法當使用ViewState作為屬性存儲時自定義服務器控件可以自行完成簡單的狀態信息管理例如 TrackViewStateSaveViewStateLoadViewState等當然開發人員也可以通過重寫方法自定義狀態管理邏輯程序在本例中視圖狀態管理過程都是由NET框架自動完成的

  下面列舉了為測試以上自定義服務器控件而創建的Defaultaspx文件源代碼

<%@ Page Language=C# AutoEventWireup=true CodeFile=Defaultaspxcs Inherits=_Default %>
<%@ ReGISter Namespace=WebControlLibrary Assembly=WebControlLibrary TagPrefix=sample %>
<!DOCTYPE html PUBLIC //WC//DTD XHTML Transitional//EN transitionaldtd
<script runat=server
 void Button_Click(object sender EventArgs e) {
   demoLabelText = TextBoxText;
   demoLabelTextInViewState = TextBoxText;
 }
</script>
<html XMLns=
<head runat=server
<title>使用視圖狀態ViewState</title>
</head>
<body >
<form id=form runat=server> <div> 姓名XML:namespace prefix = asp />

  以上代碼顯示在頁面中包括兩個文本框兩個按鈕以及一個自定義服務器控件LabelInViewState如事件處理程序 Button_Click所示當單擊提交按鈕時LabelInViewState控件將獲取文本框中文本並顯示出來應用程序效果圖如圖和圖所示



 如圖所示當用戶在兩個文本框中填寫了文本並單擊提交按鈕引發頁面回傳此時填寫的文本內容將提交到服務器並參與 Button_Click事件處理程序這樣LabelInViewState控件則顯示出了Text和TextInViewState屬性值之後當用戶單擊重載按鈕時文本框內容仍然提交到服務器但是由於沒有對應的事件處理程序因此LabelInViewState控件只顯示已經存在的狀態信息(即單擊提交按鈕之後保存的狀態)即Text屬性值為空而TextInViewState屬性值為通過以上過程可知TextInViewState屬性值都存儲在視圖狀態ViewState中因此在頁面往返過程中該屬性值得以保持而Text只簡單使用了私有變量所以狀態信息無法保持另外需要注意的是由於默認情況下頁面啟用了視圖狀態EnableViewState = true才能實現以上效果

  小結

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


From:http://tw.wingwit.com/Article/program/net/201311/13549.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.