Microsoft KB Archive/817032

From BetaArchive Wiki

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:

  1. 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.
  2. Right-click WebForm1, and then click View HTML.
  3. 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>
  4. On the Debug menu, click Start to run the application.
  5. 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.
  6. To register more than eight JScript blocks, repeat step 5 in this section of the article.
  7. 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


  1. 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.
  2. Right-click WebForm1, and then click View HTML.
  3. 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>
  4. On the Debug menu, click Start to run the application.
  5. 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.
  6. 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.

  7. 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.
  8. 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