﻿# 寫 ASP.NET 可利用 <asp:PlaceHolder> 降低 ViewState 大小

前幾天在調整一個網站的執行效能時，發現有幾頁的 [ViewState](http://www.microsoft.com/taiwan/msdn/library/2002/Jan-2002/article/Asp11222001.htm) 特別大，但是內容卻蠻簡單的，最主要就是一個 Repeater 控制項，內容不多，但 ItemTemplate 中只有用到一個 LinkButton 控制項，其他都是一般的 HTML 標籤加上 DataBound 語法 ( <%# Eval("XXX", "") %> )，由於我有用到 [UpdatePanel](http://www.asp.net/AJAX/documentation/live/Tutorials/UpdatePanelTutorials.aspx) 包住這個 Repeater 控制項，所以我 ViewState 不能關閉，關閉就會導致錯誤發生，所以我只能在 ItemTemplate 盡可能降低 ViewState 的使用，不過就因為除了 LinkButton 控制項之外的地方我都沒有可以調整的地方，才讓我想到還有個 [PlaceHolder 控制項](http://msdn.microsoft.com/zh-tw/library/system.web.ui.webcontrols.placeholder.aspx)可用。

我簡單做了個範例說明這整件事，但我把 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](http://msdn.microsoft.com/zh-tw/library/system.web.ui.databoundliteralcontrol%28VS.80%29.aspx) 控制項，而這個控制項是會保留 ViewState 的，但我們在 \*.aspx 頁面中卻無法關閉：

[![控制項樹狀結構](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/f93ef7a4df162e31abd0-image_thumb_1.png)](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/c7c79f20e3ff94663381-image_4.png)

所以我在這些 HTML 資料的前後加上一個 [PlaceHolder](http://msdn.microsoft.com/zh-tw/library/system.web.ui.webcontrols.placeholder.aspx) 控制項，並設定 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
```

**相關連結**

-   [Understanding ASP.NET View State](http://msdn.microsoft.com/en-us/library/ms972976.aspx)
-   [ViewState and Dynamic Control](http://geekswithblogs.net/FrostRed/archive/2007/02/17/106547.aspx)
-   Truly Understanding Viewstate \[瞭解 ViewState 的必讀經典\]
-   [DataBoundLiteralControl 類別](http://msdn.microsoft.com/zh-tw/library/system.web.ui.databoundliteralcontrol%28VS.80%29.aspx)
-   [PlaceHolder 類別](http://msdn.microsoft.com/zh-tw/library/system.web.ui.webcontrols.placeholder.aspx)
-   [The Will Will Web - ViewState 標籤](/?tag=/viewstate)
