Saturday, March 17, 2012

Add JavaScript programmatically using RegisterStartupScript during an Asynchronous postback


          The ClientScriptManager class contains various methods to add client scripts to a webpage using server side code. For example: you may need to add javascript programmatically to the page on a button click before posting back the page. One of the methods you can use is the  RegisterStartupScript() method of the ClientScriptManager class. However, this method does not work if the button control is wrapped inside an UpdatePanel. In this short article, we will explore how to add javascript programmatically using the ScriptManager.RegisterStartupScript, while performing an asynchronous postback. I also aim to cover some common mistakes developers make while using the ScriptManager class to add client scripts programmatically.

We will study two scenarios in this article: 

The first one, where we will use the ClientScript.RegisterStartupScript() to add script dynamically on a button click. We will add a label displaying the time, as well as change the color of the label to make sure the postback occurred.

In the second scenario, we will add the button and label control inside an UpdatePanel. We will try and use the same code, which will not work. We will then see how to add javascript programmatically during an async postback.

Scenario 1:
Create an ASP.NET project. Now add a Label(lblDisplayDate) and a Button(btnPostback) control to the page.
On the Button click, register the following script dynamically using the ClientScriptManager.RegisterStartupScript to change the color of the label controls to Red.
C#
protected void Page_Load(object sender, EventArgs e)
{
    lblDisplayDate.Text = System.DateTime.Now.ToString("T");
}

protected void btnPostback_Click(object sender, EventArgs e)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    sb.Append(@"");

    if (!ClientScript.IsStartupScriptRegistered("JSScript"))
    {
        ClientScript.RegisterStartupScript(this.GetType(), "JSScript", sb.ToString());
    }
}
VB.NET
Protected Sub Page_Load(ByVal sender As ObjectByVal e As EventArgs)
      lblDisplayDate.Text = System.DateTime.Now.ToString("T")
End Sub

Protected Sub btnPostback_Click(ByVal sender As ObjectByVal e As EventArgs)
      Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder()
      sb.Append("")

      If (Not ClientScript.IsStartupScriptRegistered("JSScript")) Then
            ClientScript.RegisterStartupScript(Me.GetType(), "JSScript", sb.ToString())
      End If
End Sub
When you run the application and click on the button, you will observe that the label is updated with a new time and the color of the label turns to red. This confirms that there was a postback, as well as the dynamically added JavaScript executed.

Scenario 2:
Now wrap the label and the button control inside an UpdatePanel as shown below:
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
        <asp:Label ID="lblDisplayDate" runat="server" Text="Label">asp:Label>
         <asp:Button ID="btnPostback" runat="server" onclick="btnPostback_Click"
        Text="ClickMe" />
    ContentTemplate>
asp:UpdatePanel>
div>
When you now run the application and click on the button, you will observe that the label is updated with the new time (which means the postback occurred), however the color of the label does not turn to red. This is because when using an Update Panel, the JavaScript that is dynamically added to the page using ClientScript.RegisterStartupScript() does not execute.
Solution:
Use the ScriptManager.RegisterStartupScript(). If you take a look at the methods of the ScriptManager class, you will observe that the methods to register client script to the page using the ClientScriptManager class, are also present in the ScriptManager class. So modify the code as shown below:
C#
protected void btnPostback_Click(object sender, EventArgs e)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    sb.Append(@"");

    ScriptManager.RegisterStartupScript(btnPostback,this.GetType(), "JSCR", sb.ToString(),false);

}
VB.NET
Protected Sub btnPostback_Click(ByVal sender As ObjectByVal e As EventArgs)
      Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder()
      sb.Append("")

      ScriptManager.RegisterStartupScript(btnPostback,Me.GetType(), "JSCR", sb.ToString(),False)

End Sub

Note 1: Observe that the last parameter to RegisterStartupScript is set to 'false'. This prevents us from inserting the