網友FrankWu在一篇留言中提到有趣的現象:

在套用jQueryClientIdEnhancement.RegisterExtScript()之後,GridView內原本沒有Id的HTML元件如<table>、<tr>、<td>開始出現id=”GridView1_ctl01”的屬性,甚至冒出<table>有兩個id的情形;若不呼叫RegisterExtScript就不會有此問題...

經實測,果真如此! 再深入做了實驗,發現問題是程式存取GridView內部控制項的ClientID屬性搞出來的,我寫了一個極簡單的網頁來驗證:

<%@ Page Language="C#" %>
<%@ Import Namespace="System.Collections.Generic" %>
<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            List<string> l = new List<string>() { "Data" };
            GridView1.DataSource = l;
            GridView1.DataBind();
            if (Request["clientid"] != null)
            {
                string cid = GridView1.Controls[0].ClientID;
            }
        }
    }
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="Button1" runat="server" Text="Button" />
        <asp:GridView ID="GridView1" runat="server">
        </asp:GridView>
    </div>
    </form>
</body>
</html>

當呼叫Test.aspx時,產生的HTML符合預期:

<table cellspacing="0" rules="all" border="1" id="GridView1" 
       style="border-collapse:collapse;">
  <tr>
    <th scope="col">Item</th>
  </tr><tr>
    <td>Data</td>
  </tr>
</table>

若呼叫Test.aspx?clientid=yes,程式會去讀取GirdView1.Controls[0].ClientID,此時傳回的HTML就會看到<table>除了原有的id=”GridView1”外,最前方又多了一組id=”GridView1_ctl00"。

<table id="GridView1_ctl00" cellspacing="0" rules="all" border="1" 
       id="GridView1" style="border-collapse:collapse;">
  <tr>
    <th scope="col">Item</th>
  </tr><tr>
    <td>Data</td>
  </tr>
</table>

用Reflector追查,發現呼叫ClientID時會觸發EnsureID(),TemplatedControl裡原本不另給Id的HTML元素(例如GridView中的<table>)會因此自動產生唯一識別碼,但在本案例中,<table>原本就有id="GridView1”,再加上自動產生的id便鬧出了雙胞。由於元素有兩個id並不符合HTML規範,我認為這算是Bug,只是,用GridView1.Controls[n]去存取這些平時根本不外露的內部控制項是很罕見的用法,因此影響有限,或許也排不上修復清單吧! 但我還是順手在Connect提報了一則Bug Report,算為ASP.NET產品的改善盡點心意。


Comments

Be the first to post a comment

Post a comment