ScriptManager.RegisterClientScriptInclude does not work in UpdatePanel

Oliver picture Oliver · Dec 16, 2009 · Viewed 10.6k times · Source

I've read through the net but haven't found a solution to the following problem. I have this example page (_ScriptManager.aspx) with a ScriptManager, an UpdatePanel, a MultiView with two Views and two LinkButtons two switch between the views. The second view contains some functionality which I want to load a JavaScript file for (_ScriptManager.js).

Since I don't know whether the user will ever visit view 2 I don't want to include the javascript file statically on for every request. I only want to load it if and when I need it. So I need to include the script file during an asynchronous postback which is what I use ScriptManager.RegisterClientScriptInclude for. The pain is: it does not work. The script include is somehow not executed on the client so that the javascript functions inside cannot be used. Even worse, the script block I register in ScriptManager.RegisterStartupScript does not get executed in this case! This is all very irritating. The interesting thing is that the include script and the script block do get sent to the client with the async postback (Fiddler is my friend :-)) and the script file is also loaded. But then the javascript somehow seems to break...

Does anyone have a clue or know of a reported bug?

_ScriptManager.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="_ScriptManager.aspx.cs" Inherits="Frontend.Web._Tests.ScriptManagerTest" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
  <title></title>
  <script src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.3.2.min.js"></script>
</head>
<body>
  <form id="form1" runat="server">
    <asp:ScriptManager runat="server" ID="scm"></asp:ScriptManager>
    <asp:Label runat="server" ID="lbOut">Outside of UpdatePanel</asp:Label>
  <div style="border: solid 1px red;">
      <asp:UpdatePanel runat="server" ID="up" UpdateMode="Conditional">
        <ContentTemplate>
          <div>
            <asp:LinkButton runat="server" ID="btnFirst">Show view 1</asp:LinkButton>
            <asp:LinkButton runat="server" ID="btnSecond">Show view 2</asp:LinkButton>
          </div>
          <div>
            <asp:MultiView runat="server" ID="mv">
              <asp:View runat="server" ID="vw1">First view - static content</asp:View>
              <asp:View runat="server" ID="vw2">
                Second view - dynamically loaded content (between dashes): 
                <div>#<span id="divDyn"></span>#</div>
              </asp:View>
            </asp:MultiView>
          </div>
        </ContentTemplate>
      </asp:UpdatePanel>
  </div>
  </form>
</body>
</html>

_ScriptManager.js (here I just add some dynamic content to the span with id=divDyn):

function dynamic() {
  alert('dynamic');
  $('#divDyn').text('Dynamic!');
}

_ScriptManager.aspx.cs code-behind:

public partial class ScriptManagerTest : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        btnFirst.Click += delegate { mv.SetActiveView(vw1); };
        btnSecond.Click += delegate { mv.SetActiveView(vw2); };

        if (!IsPostBack)
        {
            // Test 1: does not work
            mv.SetActiveView(vw1);

            // Test 2: works, because required script is loaded on initial page request
            //mv.SetActiveView(vw2);
        }
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        if (mv.GetActiveView() == vw2)
        {
            // Not calling the RegisterClientScriptInclude
            // makes the alert work in both cases, but this is
            // what it's all about: including script only when
            // needed!
            ScriptManager.RegisterClientScriptInclude(
                Page, Page.GetType(), "include-js",
                ResolveClientUrl("~/ScriptManager.js"));
            ScriptManager.RegisterStartupScript(
                this, GetType(), "call-dynamic",
                "alert('hi there'); dynamic();", true);    
        }
    }
}

Answer

Oliver picture Oliver · Dec 16, 2009

Well, this is shattering: after two 2h sessions of investigating the problem, trying ouf ALL of the possibilities of the ScriptManager, trying to use jQuery instead and finally writing up this sample (because the real world setup is as always more complicated), I now found this short blog post which solves my problem - with a single line added to the js file included:

_ScriptManager.js:

function dynamic() {
  alert('dynamic');
  $('#divDyn').text('Dynamic!');
}
// notify that the script has been loaded <-- new!
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

Well, maybe this will be of any use for anyone else out there...