ASP.NET 4 introduces more control over how client-side IDs are rendered by ASP.NET controls. By default ASP.NET 4 will render client IDs in the same way as ASP.NET 3.5 and earlier.
To change the way IDs are generated, the ClientIDMode property can be set - this can either be done on individual controls or at the page level in the @Page directive.
The default ClientIDMode value for controls is Inherit and the default for the Page is AutoID - if we change ClientIDMode at the Page level, the controls on that page will inherit the setting.
The options for ClientIDMode are:
- AutoID: (Page default) generates IDs the same way as prior versions. Use for backward compatibility or when you don't care about what IDs are generated.
- Inherit: (Control default): uses the value from the parent container.
- Static: always sets the client-side ID to the same as the server-side ID property. Use to guarantee the client-side ID of a control - may result in duplicate IDs on the client which may cause problems if you have JavaScript looking for the control by ID.
- Predictable: Can be used for content inside a databound GridView or ListView to append the unique id/key of the bound object (e.g. the primary key of a databound database record).
The following snippets of HTML output shows how the different settings change client-side IDs when a Label control called "NumberInStockLabel" is used inside a databound ListView.
AutoID, No ClientIDRowSuffix Specified
<td><span id="AutoIDListView_ctrl0_NumberInStockLabel">22</span></td>
Predictable, ClientIDRowSuffix=ProductID
<td><span id="PredictableListView_NumberInStockLabel_44">22</span></td>
The 44 at the end of the ID is the ProductID property from the underlying databound item.
Predictable, No ClientIDRowSuffix Specified
<td><span id="PredictableListViewNoClientIDRowSuffix_NumberInStockLabel_0">22</span></td>
The 0 at the end of the ID is a simple sequential number generated by ASP.NET, this is because we have not specified a value for ClientIDRowSuffix; subsequent rows would end _1 _2 _3 etc.
Static, No ClientIDRowSuffixSpecified
<td><span id="NumberInStockLabel">22</span></td>
The id is exactly the same as the one we set in markup; subsequent rows would all have exactly the same id.
Complete Source Markup
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="Products.aspx.cs"
Inherits="clientIDs.Products"
ViewStateMode="Disabled" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ObjectDataSource ID="odsProducts" runat="server"
SelectMethod="GetProducts"
TypeName="clientIDs.MockProductDB" />
<h3>ListView, AutoID, No ClientIDRowSuffix</h3>
<table>
<tr>
<th>Product ID</th>
<th>Description</th>
<th>Stock</th>
</tr>
<asp:ListView ID="AutoIDListView" runat="server"
DataSourceID="odsProducts"
ClientIDMode="AutoID"
ClientIDRowSuffix="ProductID">
<ItemTemplate>
<tr>
<td><%# Eval("ProductID") %></td>
<td><%# Eval("Description")%></td>
<td><asp:Label ID="NumberInStockLabel" runat="server" Text='<%# Eval("NumberInStock") %>' /></td>
</tr>
</ItemTemplate>
</asp:ListView>
</table>
<h3>ListView, Predictable, ClientIDRowSuffix=ProductID</h3>
<table>
<tr>
<th>Product ID</th>
<th>Description</th>
<th>Stock</th>
</tr>
<asp:ListView ID="PredictableListView" runat="server"
DataSourceID="odsProducts"
ClientIDMode="Predictable"
ClientIDRowSuffix="ProductID">
<ItemTemplate>
<tr>
<td><%# Eval("ProductID") %></td>
<td><%# Eval("Description")%></td>
<td><asp:Label ID="NumberInStockLabel" runat="server" Text='<%# Eval("NumberInStock") %>' /></td>
</tr>
</ItemTemplate>
</asp:ListView>
</table>
<h3>ListView, Predictable, No ClientIDRowSuffix set</h3>
<table>
<tr>
<th>Product ID</th>
<th>Description</th>
<th>Stock</th>
</tr>
<asp:ListView ID="PredictableListViewNoClientIDRowSuffix" runat="server"
DataSourceID="odsProducts"
ClientIDMode="Predictable">
<ItemTemplate>
<tr>
<td><%# Eval("ProductID") %></td>
<td><%# Eval("Description")%></td>
<td><asp:Label ID="NumberInStockLabel" runat="server" Text='<%# Eval("NumberInStock") %>' /></td>
</tr>
</ItemTemplate>
</asp:ListView>
</table>
<h3>ListView, Static, No ClientIDRowSuffix set</h3>
<table>
<tr>
<th>Product ID</th>
<th>Description</th>
<th>Stock</th>
</tr>
<asp:ListView ID="StaticListView" runat="server"
DataSourceID="odsProducts"
ClientIDMode="Static">
<ItemTemplate>
<tr>
<td><%# Eval("ProductID") %></td>
<td><%# Eval("Description")%></td>
<td><asp:Label ID="NumberInStockLabel" runat="server" Text='<%# Eval("NumberInStock") %>' /></td>
</tr>
</ItemTemplate>
</asp:ListView>
</table>
</div>
</form>
</body>
</html>
Complete HTML Output
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
</title></head>
<body>
<form method="post" action="Products.aspx" id="form1">
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTkwMjEwMjAxN2QYBAUOU3RhdGljTGlzdFZpZXcPFCsADmRkZGRkZGQ8KwAEAAIEZGRkZgL/////D2QFJlByZWRpY3RhYmxlTGlzdFZpZXdOb0NsaWVudElEUm93U3VmZml4DxQrAA5kZGRkZGRkPCsABAACBGRkZGYC/////w9kBRNQcmVkaWN0YWJsZUxpc3RWaWV3DxQrAA5kZGRkZGRkPCsABAACBGQVAQlQcm9kdWN0SUQUKwAEFCsAAQIsFCsAAQIDFCsAAQLIIhQrAAECYGYC/////w9kBQ5BdXRvSURMaXN0Vmlldw8UKwAOZGRkZGRkZDwrAAQAAgRkFQEJUHJvZHVjdElEFCsABBQrAAECLBQrAAECAxQrAAECyCIUKwABAmBmAv////8PZBoTurOO0ZN1r5PaB5cscPKdDFEGlp47JvHGSM55AYQ9" />
</div>
<div>
<h3>ListView, AutoID, No ClientIDRowSuffix</h3>
<table>
<tr>
<th>Product ID</th>
<th>Description</th>
<th>Stock</th>
</tr>
<tr>
<td>44</td>
<td>product 1</td>
<td><span id="AutoIDListView_ctrl0_NumberInStockLabel">22</span></td>
</tr>
<tr>
<td>3</td>
<td>product 2</td>
<td><span id="AutoIDListView_ctrl1_NumberInStockLabel">11</span></td>
</tr>
<tr>
<td>4424</td>
<td>product 3</td>
<td><span id="AutoIDListView_ctrl2_NumberInStockLabel">1</span></td>
</tr>
<tr>
<td>96</td>
<td>product 4</td>
<td><span id="AutoIDListView_ctrl3_NumberInStockLabel">0</span></td>
</tr>
</table>
<h3>ListView, Predictable, ClientIDRowSuffix=ProductID</h3>
<table>
<tr>
<th>Product ID</th>
<th>Description</th>
<th>Stock</th>
</tr>
<tr>
<td>44</td>
<td>product 1</td>
<td><span id="PredictableListView_NumberInStockLabel_44">22</span></td>
</tr>
<tr>
<td>3</td>
<td>product 2</td>
<td><span id="PredictableListView_NumberInStockLabel_3">11</span></td>
</tr>
<tr>
<td>4424</td>
<td>product 3</td>
<td><span id="PredictableListView_NumberInStockLabel_4424">1</span></td>
</tr>
<tr>
<td>96</td>
<td>product 4</td>
<td><span id="PredictableListView_NumberInStockLabel_96">0</span></td>
</tr>
</table>
<h3>ListView, Predictable, No ClientIDRowSuffix set</h3>
<table>
<tr>
<th>Product ID</th>
<th>Description</th>
<th>Stock</th>
</tr>
<tr>
<td>44</td>
<td>product 1</td>
<td><span id="PredictableListViewNoClientIDRowSuffix_NumberInStockLabel_0">22</span></td>
</tr>
<tr>
<td>3</td>
<td>product 2</td>
<td><span id="PredictableListViewNoClientIDRowSuffix_NumberInStockLabel_1">11</span></td>
</tr>
<tr>
<td>4424</td>
<td>product 3</td>
<td><span id="PredictableListViewNoClientIDRowSuffix_NumberInStockLabel_2">1</span></td>
</tr>
<tr>
<td>96</td>
<td>product 4</td>
<td><span id="PredictableListViewNoClientIDRowSuffix_NumberInStockLabel_3">0</span></td>
</tr>
</table>
<h3>ListView, Static, No ClientIDRowSuffix set</h3>
<table>
<tr>
<th>Product ID</th>
<th>Description</th>
<th>Stock</th>
</tr>
<tr>
<td>44</td>
<td>product 1</td>
<td><span id="NumberInStockLabel">22</span></td>
</tr>
<tr>
<td>3</td>
<td>product 2</td>
<td><span id="NumberInStockLabel">11</span></td>
</tr>
<tr>
<td>4424</td>
<td>product 3</td>
<td><span id="NumberInStockLabel">1</span></td>
</tr>
<tr>
<td>96</td>
<td>product 4</td>
<td><span id="NumberInStockLabel">0</span></td>
</tr>
</table>
</div>
</form>
</body>
</html>
SHARE: