保存頁的所有視圖狀態信息和控件狀態信息。
作者在早期參與的項目中曾遇到這樣的需求:基於SEO技術的開發,當因為時沒有接觸的MVC框架的Razor引擎,所以只能用ASP.NET引擎,如果使用ASP.NET引擎的服務器端控件,那麼在ASP.NET頁面中就會生成__Viewstate隱藏域,__Viewstate隱藏域產生的“亂碼”對網絡爬蟲是極其不友好的!!
“亂碼”如下:
所有問題就來了,在商業項目開發中就需要我們把__Viewstate隱藏域生成的“亂碼”去除掉。
這裡我們討論如下幾個方案。
方案一:
去掉form的標簽的 runat="server" 屬性的話,就可以不生成__viewstate隱藏域,但是服務器控件就沒法用了,所以在需要使用服務器端正控件的時候就此方法是行不通的。
方案二:
給服務器端正控件的EnableViewState屬性設置為false,此時我們發現網頁的Viewstate有明顯代碼減少,但還是存在視圖狀態。。。
方案三:
些方案需要了解.NET的一些基類,如System.Web.dll。
System.Web.dll封裝了LosFormatter類。
在MSDN上對此類的描述是: 序列化 Web 窗體頁的視圖狀態。
此時我們需要LosFormatter類裡封裝的Serialize方法,功能描述如下:將有限對象序列化 (LOS) 格式的對象轉換為視圖狀態值並將結果放置在 System.IO.Stream 對象中。
去除國“亂碼”代碼如下:
/// <summary> /// 去除VIEWSTATE亂碼代碼如下所示: /// </summary> protected LosFormatter losFormatter = new LosFormatter(); /// <summary> /// 序列化所有視圖狀態信息和控件狀態信息。 /// </summary> /// <param name="viewState">要在其中存儲視圖狀態信息的 Object</param> protected override void SavePageStateToPersistenceMedium(object viewState) { string val = Request.Url + "__VIEWSTATE"; System.IO.MemoryStream stream = new System.IO.MemoryStream(); losFormatter.Serialize(stream, viewState); stream.Flush(); Session[val] = stream; } View Code
首先要明白的是,當你按了類似Button按鈕,將頁面重新發給服務器後,服務器處理你的頁面的過程是:它會重新初始化你第一次請求的那個頁面,就是說盡管你第一次請求頁面後對這個頁面做了許多其他的操作,比如說該頁面有讓用戶隨意轉換文章字體的功能,你按了個標簽使文章字體改變了,之後又有操作按了Button按鈕將頁面回發給服務器,讓它處理你的Button事件,此時服務器重新初始化你的那個頁面,該頁面只是你第一次請求時的狀態(即未改變文章字體的狀態),但是為何服務器處理了你的Button事件,將網頁回發給你後,文章的字體的確還是你之前自定義的字體呢?不是初始化頁面的時候只是回到你第一次請求的狀態嗎?這就是viewstate的功能。在服務器初始化頁面後,它會讀取隱藏在你回發的頁面中的viewstate,從中讀取相應信息,在服務器端將文章字體變為你當初自定義的字體。 你的例子中,當在TextBox中輸入文字後,傳給服務器,服務器當然還能獲得你的輸入,唯一不同的是,如果你禁用了視圖狀態,那麼當頁面再次發給你的時候,你的TextBox就是空的了。而若沒有禁用,當頁面再次回發給你的時候,TextBox中仍然保留你上次的輸入值。
那是因為你使用了asp.net的服務器控件,如果可以盡量避免使用這種,建議使用html控件,然後runnat=server減少這種生成的"無用的值"