Microsoft KB Archive/817032

= BUG: Script Blocks Not in the Same Order of Registration When You Add Them to a Page That Uses RegisterClientScriptBlock or RegisterStartupScript =

Article ID: 817032

Article Last Modified on 5/21/2007

-

APPLIES TO


 * Microsoft ASP.NET 1.0
 * Microsoft ASP.NET 1.1

-



SYMPTOMS
When you use the RegisterClientScriptBlock method to add more then eight client-side script blocks to a page, the Script Blocks are not added in the order that you register them. Similarly, when you use RegisterStartupScript to add more then eight client-side script blocks to a page, the script blocks are not added in the order that you register them. If the execution of the client-side script depends on the order of the script block registration, then the client-side scripts may not behave as you expect.

Note You can preserve the registration order for a maximum of 16 client-side script blocks. To do so, use eight for the RegisterClientScriptBlock method and eight for the RegisterStartupScript method.



CAUSE
The registered script blocks exist in the HybridDictionary object class. If there are eight or fewer client-side script blocks, then the HybridDictionary implements with a ListDictionary class to store the items in the collection. When the collection size grows to more than eight items, the HybridDirectory switches to a Hashtable table. The ListDictionary maintains the order for added items, so that the items are retrieved in sequence. However, the Hashtable does not maintain the order of registration of the items in the collection. Therefore, the insertion of the client-side script does not occur in the serial order of registration.



RESOLUTION
To resolve this problem, add all the client-side script blocks to a StringBuilder method, and then register the StringBuilder as one script block. To do so, follow these steps:  In Microsoft Visual Studio .NET, use Microsoft Visual Basic .NET or Microsoft Visual C# .NET to create a new ASP.NET Web application project. Name the project RegJScriptBlock. By default, WebForm1.aspx is created. Right-click WebForm1, and then click View HTML.  Replace the existing code with the following code:

Visual C# .NET Code
<%@ Page language=&quot;c#&quot; %>    public void Page_Load(object sender, System.EventArgs e)       { int i = 0; string scriptKey = &quot;&quot;; if(Page.IsPostBack.Equals(false)) {               ViewState[&quot;n&quot;]=0; }           else {               ViewState[&quot;n&quot;] = Int32.Parse(ViewState[&quot;n&quot;].ToString)+1; i = Int32.Parse(ViewState[&quot;n&quot;].ToString); }

string[] nubmerOfScripts = new string[Int32.Parse(ViewState[&quot;n&quot;].ToString)+1] ; StringBuilder sb = new StringBuilder; for(int j=1;j<=i+1;j++) {               sb.Append(&quot;&quot;); sb.Append(&quot;if(&quot;+j+&quot;>1){clicked=&quot;+j+&quot;;} else {clicked=1;}&quot;); sb.Append(&quot;function DoClick&quot;+j+&quot; {&quot;); sb.Append(&quot;myForm.textCount.value=clicked} <&quot;); sb.Append(&quot;/&quot;); sb.Append(&quot;script>&quot;); sb.Append(&quot;\n&quot;); nubmerOfScripts[j-1]=sb.ToString; scriptKey = &quot;clientScript&quot;+j; }                                  // Register all  Java script  as a Single Block if(!this.IsClientScriptBlockRegistered(scriptKey)) this.RegisterClientScriptBlock(scriptKey, nubmerOfScripts[i]); }         Serial Number of the Last JavaScript Registered:<INPUT id=&quot;textCount&quot; type=&quot;text&quot;> <asp:Button id=&quot;AddScripts&quot; runat=&quot;server&quot; Text=&quot;Register JavaScript Block&quot; Height=&quot;70px&quot; Width=&quot;326px&quot;></asp:Button> </HTML>

Visual Basic .NET Code
<%@ Page Language=&quot;vb&quot; %> <%@ Import Namespace=&quot;System.Text&quot; %> <!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0 Transitional//EN&quot;> <HTML>  WebForm1 <script language= &quot;vb&quot; runat=&quot;server&quot;> Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim i As Integer Dim scriptKey As String

If (Page.IsPostBack.Equals(False)) Then

ViewState(&quot;n&quot;) = 0 Else ViewState(&quot;n&quot;) = Int32.Parse(ViewState(&quot;n&quot;).ToString) + 1 i = Int32.Parse(ViewState(&quot;n&quot;).ToString)

End If

Dim nubmerOfScripts As String ReDim nubmerOfScripts(Int32.Parse(ViewState(&quot;n&quot;).ToString))

Dim j As Integer Dim sb As New StringBuilder

For j = 1 To i + 1 Step 1 sb.Append(&quot;<script language=JavaScript>&quot;) If j > 1 Then sb.Append(&quot;clicked=&quot; + j.ToString + &quot;;&quot;) else sb.Append(&quot;clicked=1;&quot;) End If                       sb.Append(&quot;function DoClick&quot; + j.ToString + &quot; {&quot;) sb.Append(&quot;myForm.textCount.value=clicked} <&quot;) sb.Append(&quot;/&quot;) sb.Append(&quot;script>&quot;) sb.Append(Chr(13)) nubmerOfScripts(j - 1) = sb.ToString scriptKey = &quot;clientScript&quot; + j.ToString Next

' Register all JavaScript  as a Single Block If (Not (Page.IsClientScriptBlockRegistered(scriptKey))) Then Page.RegisterClientScriptBlock(scriptKey, nubmerOfScripts(i)) End If   End Sub </HEAD> <body onload=&quot;DoClick1&quot;> <form id=&quot;myForm&quot; method=&quot;post&quot; runat=&quot;server&quot;> Serial Number of the Last JavaScript Block Registered:<INPUT id=&quot;textCount&quot; type=&quot;text&quot;> <asp:Button id=&quot;AddScripts&quot; runat=&quot;server&quot; Text=&quot;Register JavaScript Block&quot; Height=&quot;70px&quot; Width=&quot;326px&quot;></asp:Button> </HTML> </li> On the Debug menu, click Start to run the application.</li> Click Register JavaScript Block to register the new JScript blocks. Each time that the JScript block is registered, the textbox displays the serial number of the last script block that is added to the Web page.</li> To register more than eight JScript blocks, repeat step 5 in this section of the article.</li> View the source on the Web page to see the order where the client script blocks are added. To do so, locate the following Web page and then right-click View Source:

http://localhost/RegJScriptBlock/WebForm1.aspx

You can see that the JScript blocks are in sequence even when the number of registered scripts is greater than eight.

</li></ol>

<div class="status_section">

STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

<div class="moreinformation_section">

Steps to Reproduce the Behavior
<ol> Start Microsoft Visual Studio .NET, and then create a new ASP.NET Web application project with Visual Basic .NET or with Visual C# .NET. Name the project RegJScriptBlock. By default, WebForm1.aspx is created.</li> Right-click WebForm1, and then click View HTML.</li>  Replace the existing code with the following code:

Visual C# .NET Code
<%@ Page language=&quot;c#&quot; %> <HTML>  <script language=&quot;C#&quot; runat=&quot;server&quot;> public void Page_Load(object sender, System.EventArgs e)       { int i = 0; string scriptKey = &quot;&quot;; if(Page.IsPostBack.Equals(false)) {               ViewState[&quot;n&quot;]=0; }           else {               ViewState[&quot;n&quot;] = Int32.Parse(ViewState[&quot;n&quot;].ToString)+1; i = Int32.Parse(ViewState[&quot;n&quot;].ToString); }

string[] nubmerOfScripts = new string[Int32.Parse(ViewState[&quot;n&quot;].ToString)+1] ;

for(int j=1;j<=i+1;j++) {               StringBuilder sb = new StringBuilder; sb.Append(&quot;<script language=JavaScript>&quot;); sb.Append(&quot;if(&quot;+j+&quot;>1){clicked=&quot;+j+&quot;;} else {clicked=1;}&quot;); sb.Append(&quot;function DoClick&quot;+j+&quot; {&quot;); sb.Append(&quot;myForm.textCount.value=clicked} <&quot;); sb.Append(&quot;/&quot;); sb.Append(&quot;script>&quot;); sb.Append(&quot;\n&quot;); nubmerOfScripts[j-1]=sb.ToString; scriptKey = &quot;clientScript&quot;+j; // Register individual JavaScript Blocks if(!this.IsClientScriptBlockRegistered(scriptKey)) this.RegisterClientScriptBlock(scriptKey, nubmerOfScripts[j-1]); }                              }       </HEAD> <body onload=&quot;DoClick1&quot;> <form id=&quot;myForm&quot; method=&quot;post&quot; runat=&quot;server&quot;> Serial Number of the Last Java Script Block Registered:<INPUT id=&quot;textCount&quot; type=&quot;text&quot;> <asp:Button id=&quot;AddScripts&quot; runat=&quot;server&quot; Text=&quot;Register JavaScript Block&quot; Height=&quot;70px&quot; Width=&quot;326px&quot;></asp:Button> </HTML>

Visual Basic .NET Code
<%@ Page Language=&quot;vb&quot; %> <%@ Import Namespace=&quot;System.Text&quot; %> <!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0 Transitional//EN&quot;> <HTML>  WebForm1 <script language= &quot;vb&quot; runat=&quot;server&quot;> Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim i As Integer Dim scriptKey As String

If (Page.IsPostBack.Equals(False)) Then

ViewState(&quot;n&quot;) = 0 Else ViewState(&quot;n&quot;) = Int32.Parse(ViewState(&quot;n&quot;).ToString) + 1 i = Int32.Parse(ViewState(&quot;n&quot;).ToString)

End If

Dim nubmerOfScripts As String ReDim nubmerOfScripts(Int32.Parse(ViewState(&quot;n&quot;).ToString))

Dim j As Integer For j = 1 To i + 1 Step 1 Dim sb As New StringBuilder sb.Append(&quot;<script language=JavaScript>&quot;) If j > 1 Then sb.Append(&quot;clicked=&quot; + j.ToString + &quot;;&quot;) else sb.Append(&quot;clicked=1;&quot;) End If                       sb.Append(&quot;function DoClick&quot; + j.ToString + &quot; {&quot;) sb.Append(&quot;myForm.textCount.value=clicked} <&quot;) sb.Append(&quot;/&quot;) sb.Append(&quot;script>&quot;) sb.Append(Chr(13)) nubmerOfScripts(j - 1) = sb.ToString scriptKey = &quot;clientScript&quot; + j.ToString 'Register individual Java Script Blocks If (Not (Page.IsClientScriptBlockRegistered(scriptKey))) Then Page.RegisterClientScriptBlock(scriptKey, nubmerOfScripts(j - 1)) End If

Next

End Sub </HEAD> <body onload=&quot;DoClick1&quot;> <form id=&quot;myForm&quot; method=&quot;post&quot; runat=&quot;server&quot;> Serial Number of the Last Java Script Block Registered:<INPUT id=&quot;textCount&quot; type=&quot;text&quot;> <asp:Button id=&quot;AddScripts&quot; runat=&quot;server&quot; Text=&quot;Register JavaScript Block&quot; Height=&quot;70px&quot; Width=&quot;326px&quot;></asp:Button> </HTML> </li> On the Debug menu, click Start to run the application.</li> Click Register JavaScript Block to register the new JScript blocks. Each time that you register the JScript block, the textbox displays the serial number of the last script block that you added to the Web page.</li> View the source on the Web page to see the order that the client script blocks are added. To do so, locate the following Web page, right-click Web page, and then click View Source:

http://localhost/RegJScriptBlock/WebForm1.aspx

You can see that the JScript blocks are in sequence until the number of registered scripts exceeds eight.

</li> To register more than eight JScript blocks, repeat step 5 in this section of the article. The value in the textbox shows the serial number of the last script in the order that it was registered (until the number of JScripts that you register exceeds eight). When the number of registered JScript blocks exceeds eight, the order is not in sequence. The order that the script blocks are added does not match the script block registration order.</li> Right-click WebForm1, and then click View Source. Note that the sequence of the JScript blocks is not the same order that you registered them.</li></ol>

<div class="references_section">