前幾天在調整一個網站的執行效能時,發現有幾頁的 ViewState 特別大,但是內容卻蠻簡單的,最主要就是一個 Repeater 控制項,內容不多,但 ItemTemplate 中只有用到一個 LinkButton 控制項,其他都是一般的 HTML 標籤加上 DataBound 語法 ( <%# Eval("XXX", "") %> ),由於我有用到 UpdatePanel 包住這個 Repeater 控制項,所以我 ViewState 不能關閉,關閉就會導致錯誤發生,所以我只能在 ItemTemplate 盡可能降低 ViewState 的使用,不過就因為除了 LinkButton 控制項之外的地方我都沒有可以調整的地方,才讓我想到還有個 PlaceHolder 控制項可用。
我簡單做了個範例說明這整件事,但我把 LinkButton 移除了,單純介紹在 Repeater 的 ItemTemplate 中的語法如何會佔用 ViewState 空間:
Default.aspx
<%@ Page Trace="true" Language="C#" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<html><body><form id="form1" runat="server">
<asp:Repeater ID="Repeater1" runat="server"> <HeaderTemplate> <ol> </HeaderTemplate>
<ItemTemplate>
<li><a href="<%# Eval("URL", "") %>"><%Eval("TITLE", "")%></a></li>
</ItemTemplate>
<FooterTemplate> </ol> </FooterTemplate> </asp:Repeater>
</form></body></html>
Default.aspx.cs
using System;
using System.Collections.Generic;
public partial class _Default : System.Web.UI.Page
{
class DataItem
{
public string URL { get; set; }
public string TITLE { get; set; }
public DataItem(string _url, string _title)
{
this.URL = _url;
this.TITLE = _title;
}
}
protected void Page_Init(object sender, EventArgs e)
{
List<DataItem> data = new List<DataItem>();
data.Add(new DataItem("http://www.miniasp.com/", "多奇數位"));
data.Add(new DataItem("http://blog.miniasp.com/", "The Will Will Web"));
data.Add(new DataItem("http://msg.nat.gov.tw/", "我的貼身e管家"));
Repeater1.DataSource = data;
Repeater1.DataBind();
}
}
在以上範例中,你會看到在 ItemTemplate 中有出現一段
<li><a href="<%# Eval("URL", "") %>"><%Eval("TITLE", "")%></a></li>
但是我開啟 Page Trace 之後,卻發現這一段是會佔用不少 ViewState 的,而且會將原本應該產生 LiteralControl 的,因為使用了 DataBound 的語法而被轉成 DataBoundLiteralControl 控制項,而這個控制項是會保留 ViewState 的,但我們在 *.aspx 頁面中卻無法關閉:
所以我在這些 HTML 資料的前後加上一個 PlaceHolder 控制項,並設定 EnableViewState 為 false 就可以把 ViewState 全部關掉了,若你 ItemTemplate 中的資料量很大的話,可省下的空間不可小覷。
更新過的 Default.aspx 如下:
<%@ Page Trace="true" Language="C#" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<html><body><form id="form1" runat="server">
<asp:Repeater ID="Repeater1" runat="server"> <HeaderTemplate> <ol> </HeaderTemplate>
<ItemTemplate>
<asp:PlaceHolder runat="server" ID="PlaceHolder1" EnableViewState="false">
<li><a href="<%# Eval("URL", "") %>"><%Eval("TITLE", "")%></a></li>
</asp:PlaceHolder>
</ItemTemplate>
<FooterTemplate> </ol> </FooterTemplate> </asp:Repeater>
</form></body></html>
若想看由 ASP.NET 自動產生的 *.cs 程式原始碼的話,可以修改 web.config 中在 <system.web> 底下的 <compilation debug="false"> 改成 <compilation debug="true"> 後,重新執行一遍這一頁,再到 Temporary ASP.NET Files 目錄下查看產生過的原始碼即可,通常這個目錄預設會放在以下路徑:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files
相關連結