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="c#" %> <HTML> <HEAD> <script language="C#" runat="server"> public void Page_Load(object sender, System.EventArgs e) { int i = 0; string scriptKey = ""; if(Page.IsPostBack.Equals(false)) { ViewState["n"]=0; } else { ViewState["n"] = Int32.Parse(ViewState["n"].ToString())+1; i = Int32.Parse(ViewState["n"].ToString()); } string[] nubmerOfScripts = new string[Int32.Parse(ViewState["n"].ToString())+1] ; StringBuilder sb = new StringBuilder(); for(int j=1;j<=i+1;j++) { sb.Append("<script language=JavaScript>"); sb.Append("if("+j+">1){clicked="+j+";} else {clicked=1;}"); sb.Append("function DoClick"+j+"() {"); sb.Append("myForm.textCount.value=clicked} <"); sb.Append("/"); sb.Append("script>"); sb.Append("\n"); nubmerOfScripts[j-1]=sb.ToString(); scriptKey = "clientScript"+j; } // Register all Java script as a Single Block if(!this.IsClientScriptBlockRegistered(scriptKey)) this.RegisterClientScriptBlock(scriptKey, nubmerOfScripts[i]); } </script> </HEAD> <body onload="DoClick1()"> <form id="myForm" method="post" runat="server"> Serial Number of the Last JavaScript Registered:<INPUT id="textCount" type="text"><br> <asp:Button id="AddScripts" runat="server" Text="Register JavaScript Block" Height="70px" Width="326px"></asp:Button> </form> </body> </HTML>
Visual Basic .NET Code
<%@ Page Language="vb" %> <%@ Import Namespace="System.Text" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <title>WebForm1</title> <script language= "vb" runat="server"> 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("n") = 0 Else ViewState("n") = Int32.Parse(ViewState("n").ToString()) + 1 i = Int32.Parse(ViewState("n").ToString()) End If Dim nubmerOfScripts As String() ReDim nubmerOfScripts(Int32.Parse(ViewState("n").ToString())) Dim j As Integer Dim sb As New StringBuilder() For j = 1 To i + 1 Step 1 sb.Append("<script language=JavaScript>") If j > 1 Then sb.Append("clicked=" + j.ToString() + ";") else sb.Append("clicked=1;") End If sb.Append("function DoClick" + j.ToString() + "() {") sb.Append("myForm.textCount.value=clicked} <") sb.Append("/") sb.Append("script>") sb.Append(Chr(13)) nubmerOfScripts(j - 1) = sb.ToString() scriptKey = "clientScript" + 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 </script> </HEAD> <body onload="DoClick1()"> <form id="myForm" method="post" runat="server"> Serial Number of the Last JavaScript Block Registered:<INPUT id="textCount" type="text"><br> <asp:Button id="AddScripts" runat="server" Text="Register JavaScript Block" Height="70px" Width="326px"></asp:Button> </form> </body> </HTML>
- On the Debug menu, click Start to run the application.
- 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.
- To register more than eight JScript blocks, repeat step 5 in this section of the article.
- 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:
You can see that the JScript blocks are in sequence even when the number of registered scripts is greater than eight.
STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.
MORE INFORMATION
Steps to Reproduce the Behavior
- 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.
- Right-click WebForm1, and then click View HTML.
Replace the existing code with the following code:
Visual C# .NET Code
<%@ Page language="c#" %> <HTML> <HEAD> <script language="C#" runat="server"> public void Page_Load(object sender, System.EventArgs e) { int i = 0; string scriptKey = ""; if(Page.IsPostBack.Equals(false)) { ViewState["n"]=0; } else { ViewState["n"] = Int32.Parse(ViewState["n"].ToString())+1; i = Int32.Parse(ViewState["n"].ToString()); } string[] nubmerOfScripts = new string[Int32.Parse(ViewState["n"].ToString())+1] ; for(int j=1;j<=i+1;j++) { StringBuilder sb = new StringBuilder(); sb.Append("<script language=JavaScript>"); sb.Append("if("+j+">1){clicked="+j+";} else {clicked=1;}"); sb.Append("function DoClick"+j+"() {"); sb.Append("myForm.textCount.value=clicked} <"); sb.Append("/"); sb.Append("script>"); sb.Append("\n"); nubmerOfScripts[j-1]=sb.ToString(); scriptKey = "clientScript"+j; // Register individual JavaScript Blocks if(!this.IsClientScriptBlockRegistered(scriptKey)) this.RegisterClientScriptBlock(scriptKey, nubmerOfScripts[j-1]); } } </script> </HEAD> <body onload="DoClick1()"> <form id="myForm" method="post" runat="server"> Serial Number of the Last Java Script Block Registered:<INPUT id="textCount" type="text"><br> <asp:Button id="AddScripts" runat="server" Text="Register JavaScript Block" Height="70px" Width="326px"></asp:Button> </form> </body> </HTML>
Visual Basic .NET Code
<%@ Page Language="vb" %> <%@ Import Namespace="System.Text" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <title>WebForm1</title> <script language= "vb" runat="server"> 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("n") = 0 Else ViewState("n") = Int32.Parse(ViewState("n").ToString()) + 1 i = Int32.Parse(ViewState("n").ToString()) End If Dim nubmerOfScripts As String() ReDim nubmerOfScripts(Int32.Parse(ViewState("n").ToString())) Dim j As Integer For j = 1 To i + 1 Step 1 Dim sb As New StringBuilder() sb.Append("<script language=JavaScript>") If j > 1 Then sb.Append("clicked=" + j.ToString() + ";") else sb.Append("clicked=1;") End If sb.Append("function DoClick" + j.ToString() + "() {") sb.Append("myForm.textCount.value=clicked} <") sb.Append("/") sb.Append("script>") sb.Append(Chr(13)) nubmerOfScripts(j - 1) = sb.ToString() scriptKey = "clientScript" + j.ToString() 'Register individual Java Script Blocks If (Not (Page.IsClientScriptBlockRegistered(scriptKey))) Then Page.RegisterClientScriptBlock(scriptKey, nubmerOfScripts(j - 1)) End If Next End Sub </script> </HEAD> <body onload="DoClick1()"> <form id="myForm" method="post" runat="server"> Serial Number of the Last Java Script Block Registered:<INPUT id="textCount" type="text"><br> <asp:Button id="AddScripts" runat="server" Text="Register JavaScript Block" Height="70px" Width="326px"></asp:Button> </form> </body> </HTML>
- On the Debug menu, click Start to run the application.
- 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.
- 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:
You can see that the JScript blocks are in sequence until the number of registered scripts exceeds eight.
- 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.
- 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.
REFERENCES
For more information about the RegisterClientScriptBlock method, visit the following Microsoft Developer Network (MSDN) Web sites:
Page.RegisterClientScriptBlock Method
http://msdn2.microsoft.com/en-us/library/system.web.ui.page.registerclientscriptblock(vs.71).aspx
Page.RegisterStartupScript Method
http://msdn2.microsoft.com/en-us/library/system.web.ui.page.registerstartupscript(vs.71).aspx
Keywords: kbscript kbwebserver kbwebforms kbbug KB817032