Accessing ClientID or UniqueID too early can cause issues

Posted by: Jotekes Blog, on 28 Jan 2007 | View original | Bookmarked: 0 time(s)

I've seen lately a few issues on newsgroups related to ASP.NET 2.0 cases where ClientID or UniqueID of a Control is accessed before the control tree is fully constructed, which leads to rendered ClientID and UniqueID being wrong. Final issue is that these prevent postback events from working as UniqueID is used with postback data routing. Here's a simple case to repro it.

Assume we have a  DataGrid with a Button.

<asp:DataGrid ID="DataGrid1" runat="server"  AutoGenerateColumns="false" OnItemCreated="DataGrid1_ItemCreated" >
     <Columns>
        <asp:TemplateColumn>
           <ItemTemplate>
             <asp:Button ID="Button1" runat="server" Text="Click me" OnClick="Button1_Click" />
           </ItemTemplate>
        </asp:TemplateColumn>
     </Columns>
</asp:DataGrid>

And relevant code

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            ArrayList list = new ArrayList();
            list.Add(1);
            list.Add(2);
            list.Add(3);

            DataGrid1.DataSource = list;
            DataGrid1.DataBind();
        }
    }

    protected void DataGrid1_ItemCreated(object sender, DataGridItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            //Touching the clientID too early causes rendered ids to be wrong
            // which also impacts on postback routing etc etc

            //comment the line(s) to make clicks work
            string s = e.Item.FindControl("Button1").ClientID;
            //string s = e.Item.FindControl("Button1").UniqueID;
        }
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        Response.Write("Button1_Click");
    }
   

The lines in ItemCreated accessing ClientID or UniqueID are the catch. If they (either or both) are uncommented, the grid renders as

 <table cellspacing="0" rules="all" border="1" id="DataGrid1" style='border-collapse:collapse;'>
 <tr>
  <td> </td>
 </tr><tr>
  <td>
                    <input type="submit" name="Button1" value="Click me" id="Button1" />
                </td>
 </tr><tr>
  <td>
                    <input type="submit" name="Button1" value="Click me" id="Button1" />
                </td>
 </tr><tr>
  <td>
                    <input type="submit" name="Button1" value="Click me" id="Button1" />
                </td>
 </tr>
 </table>

However, if you comment the lines you'll see

<table cellspacing="0" rules="all" border="1" id="DataGrid1" style='border-collapse:collapse;'>
 <tr>
  <td> </td>
 </tr><tr>
  <td>
                    <input type="submit" name="DataGrid1$ctl02$Button1" value="Click me" id="DataGrid1_ctl02_Button1" />
                </td>
 </tr><tr>
  <td>
                    <input type="submit" name="DataGrid1$ctl03$Button1" value="Click me" id="DataGrid1_ctl03_Button1" />
                </td>
 </tr><tr>
  <td>
                    <input type="submit" name="DataGrid1$ctl04$Button1" value="Click me" id="DataGrid1_ctl04_Button1" />
                </td>
 </tr>
 </table>

The difference in behavior is that in other case Button's Click event is raised while in the other it isn't.

Based on my current investigation this relates to UniqueID getting cached too early due to early access (it is implemented in get accessor of ClientID and UniqueID properties) or that's how I've understood it. In ItemCreated the DataGridItem isn't yet added to Controls collection of the grid, which means that the full control tree from the Button to the Page isn't final. Accessing ClientID or UniqueID at this point causes the issue.

Cause itself is clear: Accessing ClientID and UniqueID too early is wrong but question is that is the behaviour too unintuitive as-is? Should it not cache the id till the control tree is done or should it throw an exception (that could be exaggerated but also an option )? I think that just accessing a property causing this type of behaviour is a bit too "mystical". :-)

I do understand it, but seems that there are people getting quite confused because of it. And because of no exceptions etc, it might be harder to debug and correct. Solution itself is very simple once you understand the issue.

Opinions?

Share this post: email it! | bookmark it! | digg it! | reddit! | kick it! | live it!

Advertisement
Free Agile Project Management Tool from Telerik
TeamPulse Community Edition helps your team effectively capture requirements, manage project plans, assign and track work, and most importantly, be continually connected with each other.
Category: DataGrid | Other Posts: View all posts by this blogger | Report as irrelevant | View bloggers stats | Views: 2334 | Hits: 32

Similar Posts

  • IIS Search Engine Optimization Toolkit more
  • Silverlight Toolkit March 2009 Release more
  • Accessibility and RadEditor more
  • Some RadToolTip tips & tricks more
  • Grayed out ASP.NET Toolbox Controls? Check your Mouse! more
  • December's Toolbox Column Online more
  • TestMatrix - Enhanced Support For Test Driven Development and Unit Testing In Visual Studio more
  • WPF: Welcome Super ToolTips - Office 2007 style more
  • ToolBars in Avalon more
  • Missing the Navigate Forward and Navigate Backward commands on your Toolbar more

News Categories

.NET | Agile | Ajax | Architecture | ASP.NET | BizTalk | C# | Certification | Data | DataGrid | DataSet | Debugger | DotNetNuke | Events | GridView | IIS | Indigo | JavaScript | Mobile | Mono | Patterns and Practices | Performance | Podcast | Refactor | Regex | Security | Sharepoint | Silverlight | Smart Client Applications | Software | SQL | VB.NET | Visual Studio | W3 | WCF | WinFx | WPF | WSE | XAML | XLinq | XML | XSD