Wednesday, 28 July 2010

What's New in ASP.NET 4.0 - ClientID Generation for a Cleaner MarkUp

In order to avoid naming conflicts in controls, ASP.NET 2.0/3.5 used ClientID’s, which made each control generate the id attribute unique to that page. However these ID’s generated were long and unpredictable. Developers who have been doing Client-Side programming using a scripting language like JavaScript, have sorrow tales to tell when it came to referencing those ClientID’s in their scripts.
ASP.NET 4.0 through the new ClientIDMode property, now gives control back to the developer over the ClientID’s generated by ASP.NET controls. In my personal opinion, this was a good design decision taken by the ASP.NET team, since a lot of ASP.NET developers are using Client-side programming to enhance their interfaces and popular JavaScript frameworks like jQuery are getting more popular.
ClientID in ASP.NET 2.0/3.5
Let us first observe the behavior of ClientID in ASP.NET 2.0/3.5. Drop a Panel control and a Button Control in a Content Page as shown below:
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<asp:Panel ID="PanelParent" runat="server">
<asp:Panel ID="PanelChild" runat="server">
<asp:Button ID="ButtonOne" runat="server" Text="SomeButton" />
asp:Panel>
asp:Panel>
asp:Content>
When you run this page and view page source, the following ClientID’s would have been generated
<div id="ctl00_ContentPlaceHolder1_PanelParent">            
  <div id="ctl00_ContentPlaceHolder1_PanelChild">                    
 <input type="submit" name="ctl00$ContentPlaceHolder1$ButtonOne" value="SomeButton" 
id="ctl00_ContentPlaceHolder1_ButtonOne" />        
  div>    
div>
Needless to say, although the generated ID’s serve their purpose well, they are long and are a pain to refer in your scripts.
Client ID’s in ASP.NET 4.0
ASP.NET 4.0 introduces the ClientIDMode property using which you can generate clean and predictable ID’s for controls. The ClientIDMode property accepts an enumeration that are as follows:
· AutoID – This specifies an algorithm that is the same for generating ClientID property values in ASP.NET 2.0/3.5.
· Static – This specifies that the ClientID property value will be the same as the ID specified by the developer.
· Predictable – This specifies an option that is useful for data controls like the GridView, Repeater etc. Although using this option concatenates the ID properties of the control's naming containers, however the ID’s generated do not contain strings like "ctlxxx". Along with this option, you can also use a new property called the ClientIDRowSuffix property of the control. You set the ClientIDRowSuffix property to the name of a data field, and the value of that field is used as the suffix for the generated ClientID value.
· Inherit – This specifies that a control's ID generation is the same as its parent (I have marked my observations while explaining this property)
The ClientIDMode property can be set on individual controls, on the page or at the application level
· Individual Controls
<asp:Panel ID="PanelChild" runat="server" ClientIDMode="Static">
· Page level
<%@ Page Title="Sample" Language="C#"
MasterPageFile="~/MasterPage.master"
AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default"
ClientIDMode="Static" %>
· Web.config file
<system.web>
<pages clientIDMode="Static">pages>
system.web>
Note: The default ClientIDMode value at the page level is ‘AutoID’ and at the Control level is ‘Inherit’
Now let us use the same example I used in the beginning (for ASP.NET 3.5), in an ASP.NET 4.0 Master-Content Page scenario. We will be using the new ClientIDMode property on individual controls.
ClientIDMode=”AutoID”
The result is the same as for ASP.NET 2.0/3.5
<div id="ctl00_ContentPlaceHolder1_PanelParent">            
   <div id="ctl00_ContentPlaceHolder1_PanelChild">                    
 <input type="submit" name="ctl00$ContentPlaceHolder1$ButtonOne" value="SomeButton" 
id="ctl00_ContentPlaceHolder1_ButtonOne" />                   
   div>    
div>
ClientIDMode=”Static”
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<asp:Panel ID="PanelParent" runat="server" ClientIDMode="Static">
<asp:Panel ID="PanelChild" runat="server" ClientIDMode="Static">
<asp:Button ID="ButtonOne" runat="server" Text="SomeButton" ClientIDMode="Static"/>
asp:Panel>
asp:Panel>
asp:Content>
is rendered as
<div id="PanelParent">            
  <div id="PanelChild">                    
 <input type="submit" name="ctl00$ContentPlaceHolder1$ButtonOne" value="SomeButton" id="ButtonOne" />                   
  div>    
div>
ClientIDMode=”Predictable”
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<asp:Panel ID="PanelParent" runat="server" ClientIDMode="Static">
<asp:Panel ID="PanelChild" runat="server" ClientIDMode="Predictable">
<asp:Button ID="ButtonOne" runat="server" Text="SomeButton"/>
asp:Panel>
asp:Panel>
asp:Content>
Is rendered as :
<div id="PanelParent">            
   <div id="ContentPlaceHolder1_PanelChild">                    
 <input type="submit" name="ctl00$ContentPlaceHolder1$ButtonOne" value="SomeButton" 
id="ContentPlaceHolder1_ButtonOne" />      
        
   div>    
div>
Note: The ClientIDMode=”Predictable” is very useful to predict ID’s of child controls kept inside databound controls like the GridView or the Repeater. You should also look at the ClientIDRowSuffix property. We will cover this in one of the future articles.
ClientIDMode=”Inherit”
This one is a tricky one and unfortunately it’s not very clearly explained in the documentation. So let me make an attempt. The documentation suggests that by using ‘Inherit’, the control inherits the ClientIDMode setting of its parent control. So that means that if I set the ClientIDMode of the parent control to ‘Static’ and the child control to ‘Inherit’, the child control’s resultant ClientID should be ‘Static’
However on running this piece of code:
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1"
Runat="Server">
<asp:Panel ID="PanelParent" runat="server">
<asp:Panel ID="PanelChild" runat="server" ClientIDMode="Static">
<asp:Button ID="ButtonOne" runat="server" Text="SomeButton"
ClientIDMode="Inherit" />
asp:Panel>
asp:Panel>
asp:Content>
I get
<div id="ContentPlaceHolder1_PanelParent">
<div id="PanelChild">
<input type="submit" name="ctl00$ContentPlaceHolder1$ButtonOne" value="SomeButton" id="ContentPlaceHolder1_ButtonOne" />
div>
div>
Uhmm! Not quite as expected. I was expecting the ID of the button to be rendered as ‘ButtonOne’.
What is actually happening here is that the ‘Inherit’ attribute derives its ID naming from its Naming Container and not the Parent Container. So setting the ClientIDMode to ‘Static’ for the ContentPlaceHolder (Naming container) gets us the desired results
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1"
Runat="Server" ClientIDMode="Static">
<asp:Panel ID="PanelParent" runat="server">
<asp:Panel ID="PanelChild" runat="server" ClientIDMode="Predictable">
<asp:Button ID="ButtonOne" runat="server" Text="SomeButton"
ClientIDMode="Inherit" />
asp:Panel>
asp:Panel>
asp:Content>
is rendered as
<div id="PanelParent">
<div id="ContentPlaceHolder1_PanelChild">
<input type="submit" name="ctl00$ContentPlaceHolder1$ButtonOne" value="SomeButton" id="ButtonOne" />
div>
div>
In this article, we saw that using the ClientIDMode property in ASP.NET 4.0, we can generate cleaner HTML markup from server controls. In the forthcoming articles, we will explore some more improvements in ASP.NET 4.0
I hope you liked the article and I thank you for viewing it.

No comments:

Post a Comment