Controlling our ClientIDs in ASP.NET 4

Introduction to ClientIDs in ASP.NET 4

Microsoft has released ASP.NET 4 with a lot of new features. One that seems small on the surface is a feature that I am very excited about. It has the potential to really clean up my code, and make JavaScript a lot easier for me to write and maintain. This little feature that could is the ClientIDMode property that lets you define how client ids are maintained in your ASP.NET code.

What are ClientIDs?

Each control on an ASP.NET page has two names. The first is the control name, and this is the name of that object as it relates to code on the server side. When you want to access the text property of a text box you will use the control name to do so. In the .aspx file you would declare the text box control:

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

And in your code behind you would refer to it as so:

string newName = TextBox1.Text;

But when it comes to referring to this text box from within the browser (most likely with JavaScript or a framework on JavaScript like JQuery) ASP.NET generates a client side ID for it. This is called the client id. In many scenarios this client id is the same as the control id. If you view the source of your site, you will see this in action. If we put a textbox and a button on a normal .aspx page you will see this for the HTML:

This isn’t too bad to work with since the client id matches the control id we are used to. But when you put these same controls inside a content placeholder as part of a master page (or a grid, or any other control container), a whole new set of client ids appear. This is because they now have a nested relationship.

So now in my JavaScript I have to refer to a control called'ctl00_ContentPlaceHolder1_Button1' instead of just 'Button1'. This leads to messy, hard to maintain code.

How the Control Tree Works

All controls on your page are organized in a tree structure on the page by ASP.NET. In our first example, all of the controls were direct children of the form itself. In our second example they became children of the content placeholder control, which itself was a child of the form. This tree represents the hierarchy, or family structure, of the controls and how they related to one another.

ASP.NET generates names for your controls at runtime based on this tree. If there is just one level, they are given names that are the same (or similar) to their control id. If, you have controls nested, then the name is a concatenation of the controls name, and all of its parents, in one long string. This is to avoid any naming conflicts between all of the controls on the page.

This doesn’t look hard in our simple sample, but take a look at a dynamically generated grid with a hundred rows and ten columns and your head will explode (sample not provided because we are concerned with your safety).

How to Control your Client ID

ASP.NET 4 has a new feature that lets you control the client ids generated for your controls. You can control this at the application level, the page level, or at the control level, to suit your needs. You can control this behavior by setting a property called ClientIDMode.

There are four options for this new property:

AutoID: This follows the old behavior, resulting in long, complex, and extremely unique client ids. You might use this mode if this behavior doesn’t bother you, or perhaps you have some legacy JavaScript you don’t have time to update yet.

Static: This forces the client id to always match the control id (or the ID parameter on the control). This is very nice and gives you a consistent naming structure on the client and the server, but does leave open the problem of conflicting control names in some scenarios. This is my preferred setting when I can get away with it.

Predictable: This uses the same algorithm as the AutoID mode to generate names, but it avoids the crazy parent control prefixes like ct100_. This setting makes sure you have no conflicts in names, but keeps them somewhat cleaner. When working with a container control, like a grid, that will have a lot of child controls you can force your own prefix (example: salesGrid), giving you some control over your code readability. To do this you would set the ClientIDRowSuffix property on the parent control.

Inherit: This mode tells the control to inherit its naming behavior from its naming container (which may not necessarily be its control container).

How to Use It

To declare this for the entire web application you have to add a setting to your web.config in thesystem.web section.

<system.web>
<pages clientIDMode="AutoID"></pages>
</system.web>

In this example I set the behavior to AutoID. Remember that this feature is only supported in ASP.NET 4, so you have to change the .NET framework version of your project in the project properties before this will work.

To change the naming behavior for just a single page (perhaps you want to migrate one page at a time from the old way to the new way) you would add a property to the page declaration in the aspx file.

Summary

Prior to ASP.NET 4 client ids were generated for you, sometimes resulting in ids that were very hard to work with. This behavior did make sure that with all of the nested controls on the screen you never ended up with a naming conflict on a control, it did result in some hairy JavaScript.

With ASP.NET 4 you can now use the ClientIDMode property to control how ASP.NET names your controls. The setting can be declared for the whole application, just a page, or a single control. You can set it to continue naming controls the old way, forcing a specific control name, or to use a new cleaner way to name them. You also have the option of telling a control to inherit the naming behavior from its naming parent.