All posts

The difference between ID, ClientID and UniqueID

I this post I will try to explain the difference between those three commonly used properties. Each property is described in a separate section. Attached you can find a sample web site as well as two screenshots visually depicting the difference between the ID, ClientID and UniqueID properties.

 

ID

The ID property is used to assign an identifier to an ASP.NET server control which can be later used to access that control. You can use either the field generated in the codebehind or pass the value of the ID property to the FindControl method. There is a catch though - the ID property is unique only within the current NamingContainer (page, user control, control with item template etc). If a server control is defined inside the item template of some other control (Repeater, DataGrid) or user control, its ID property is no longer unique. For example, you can add some user control twice in the same page. Any child controls of that user control will have the same ID.  Also the ASP.NET page parser won’t generate a codebehind field corresponding to the control ID in case the control is defined inside a template. This is the reason you cannot easily find a specific control when it is part of a template - you need to use the FindControl method of its container control instead. As a side note, setting the ID property is not mandatory. If you don’t set it the ASP.NET Runtime will generate one for you in the form of “_ctl0”, “_ctl1”, etc.

 

UniqueID

The UniqueID property is the page-wide unique identifier of an ASP.NET server control. Its uniqueness is guaranteed by prefixing the ID of a server control with the ID of its NamingContainer. If the NamingContainer is the Page the UniqueID will remain the same as the ID.

For example if a Label with ID="Label1" is defined in a user control with ID = "UserControl1" the UniqueID of the Label will be "UserControl1$Label1". Adding another instance of the same user control (with ID = "UserControl2") will make the UniqueID of its child label to be "UserControl2$Label1".

The UniqueID property is also used to provide value for the HTML "name" attribute of input fields (checkboxes, dropdown lists, and hidden fields). UniqueID also plays major role in postbacks. The UniqueID property of a server control, which supports postbacks, provides data for the __EVENTTARGET hidden field. The ASP.NET Runtime then uses the __EVENTTARGET field to find the control which triggered the postback and then calls its RaisePostBackEvent method. Here is some code which illustrates the idea:

IPostBackEventHandler postBackInitiator =

Page.FindControl(Request.Form["__EVENTTARGET") As IPostBackEventHandler;

if (postBackInitiator != null)
    postBackInitiator.RaisePostBackEvent(Request.Form["__EVENTARGUMENT"]);

You can use the UniqueID property to find any control no matter how deep it is nested in the control hierarchy. Just pass its value to the FindControl method of the Page.
 

ClientID

The ClientID property is quite similar to the UniqueID. It is generated following the same rules (the ID of the control prefixed by the ID of its NamingContainer). The only difference is the separator - for the ClientID it is the "_" (underscore) symbol.
The ClientID property is globally unique among all controls defined in an ASP.NET page. You may ask why we need two different globally unique properties. The answer is that ClientID serves a different purpose than UniqueID. In most server controls the ClientID property provides the value for the HTML "id" attribute of the HTML tag of that server control. For example this:

<asp:Label ID="Label1" Text="Label" />

will render as this:

<span id="Label1">Label</span>

 

That’s why you often use the following JavaScript statement to access the DOM element corresponding to some ASP.NET server control:

var label = document.getElementById("<%= Label1.ClientID%>");

which in turn renders as:

var label = document.getElementById("Label1");

 

It is worth mentioning that the values of the ID, UniqueID and ClientID will be the same if the control is defined in the master page (or the page). This however can often lead to unexpected errors. If the ID of the control is hardcoded inside the JavaScript statement (e.g. "Label1") this code will only work provided the control is defined in the Page or master page. Moving the control and the JavaScript code into a userc control with ID "UserControl1" will fail at runtime because the control will now render as:

<span id="UserControl1_Label1">Label</span>

That’s why you should prefer using the "<%= Label1.ClientID%>" syntax to get the client-side id of server controls.

Additionaly the ClientID is used in ASP.NET Ajax as the unique identifier of client-side controls. Thus the following JavaScript statement is commonly used:

var control = $find("<%= MyControl1.ClientID %>");

Example

I have attached a sample web site which demonstrates the difference between those three properties of controls defined in a page (without a master), master page, content placeholder and user control. Here are two screenshots from the output:

Normal ASPX page (without a master page):


Master page scenario:

 

I hope this helps.

Facebook DZone It! Digg It! StumbleUpon Technorati Del.icio.us NewsVine Reddit Blinklist Furl it!

Comments  12

  • 7 Jun, 07:38 PM

    seriously, "You can use the UniqueID property to find any control no matter how deep it is nested in the control hierarchy. Just pass its value to the FindControl method of the Page" saved my day! Thanks for that great article!

    peter

  • 10 Jun, 09:38 AM

    Hi Atanas, nice post. I already wrote about this in codeproject http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=551869. But I still have some unanswered questions: Why to generate three values almost equals (only the separator differs between them) UniqueID, ClientID an 'name'? Is it a browser issue handling client ID with the '$' char and so replace them with '_'? Why not make client 'name' attribute equals UniqueID? Can you answer any of this questions?

    Nuno Gomes

  • 12 Jun, 09:08 AM

    Frankly speaking I can only guess why the ASP.NET team decided to render different values for the "name" and "id" HTML attributes. As far as I know having the dollar character in the "id" attribute is not XHTML compliant. However using underscores as separators is XHTML compliant (for both "id" and "name".) Also there seems to be no problem to have both the "id" and "name" set to the same value (e.g. "UserControl1_TextBox1"). I suspect the ASP.NET guys just wanted those attributes to have different values and maybe this is the reason UniqueID and ClientID are sometimes different. Still it is a valid argument that in some cases (maybe in 50% of all cases) those properties have the same value.

    Atanas Korchev

  • 13 Jul, 10:13 PM

    I think this is the best explanation possible. Thanks

    Prashant Gupta

  • 13 Aug, 11:00 PM

    Great article!!

    Xu

  • 18 Aug, 05:42 AM

    Nice aticle

    Nirmallya Kolay

  • 26 Aug, 05:11 PM

    Hi, just found your Telerik blogs and what a mine of info...on this particular subject I always seem to have trouble when writing javascript using %= Label1.ClientID% when the control is within templates. Say Label1 is in both FormView EditItemTemplate and ItemTemplate...is it just me?

    Martin P

  • 27 Aug, 09:38 PM

    Good article. I have an issue, however, and thought that you might know that solution... I have a search page with sub-controls, the sub-controls have fields. When I first execute the search on it, the Request object has the same key-name for a field in Params.AllKeys as the UniqueId of the field (e.g. ctl00$ContentPlaceHolder1$mySubControl$txtExample). After returning to the search page and repopulating the search parameters, and then executing a search, the Request object no longer has the same key-name for the same field (it has now changed to: ctl00$ContentPlaceHolder1$ctl00$txtExample) as a result, it is not possible to read the field in the code behind (I can still call this.txtExample.Text, but it won't have a value as the value held in Request is never populated into it). Any thoughts on why this might happen or how to get around it (creating a monolithic control is not desired)?

    Reow

  • 29 Aug, 06:36 AM

    @Martin Unfortunately you cannot use server-side blocks in templates because templates are usually instantiated later. Those blocks are evaluated during page parse time hence you can only use controls which have a field declared for them in codebehind. @Reow It seems that the mySubControl lost its ID for some reason. Keep in mind the ID property is not persisted in ViewState between postbacks and you need to set it on every page load if you depend on it later.

    Atanas Korchev

  • 7 Oct, 03:44 AM

    "As far as I know having the dollar character in the "id" attribute is not XHTML compliant. However using underscores as separators is XHTML compliant (for both "id" and "name".)" The id has _, and the name has $ as separator, both xhtml compliant. "Also there seems to be no problem to have both the "id" and "name" set to the same value" No, this could be a big problem in IE! This is because getElementsByName returns also dom elements with matching ids(!) This is a bug in ie, here is an example: http://www.romantika.name/v2/javascripts-getelementsbyname-ie-vs-firefox/

    stm

  • 16 Oct, 11:01 AM

    Atanas, Simply speaking you are great. I was struck up with this particular topic in ASP.Net Code. Reading this really provided me the correct understanding. Thanks for providing this useful article. Thanks and Regards Kunal Shrivastava

    kunal shrivastava

  • 25 Mar, 01:06 PM

    Nice Post!

    Koppaka Venkata

Post a comment!
  1. Formatting options
       
     
     
     
     
       
  2. Security image