AJAX >> Using AJAX to load a usercontrol that has JavaScript declared in it

Monday, October 20, 2008 by Tervel Peykov & Svetlina Anati | Comments 10

One of the things one needs to take care of when converting an existing application to use MS AJAX is inline script blocks inside pages or user controls. Problem with these is that if the control is sent to the client as a result of a partial page update (e.g. AJAX call) the inline script block simply won’t execute at all.

The problem is caused by the way MS AJAX and browsers work.

When an UpdatePanel is to replace its old content with newly received AJAX content, it deletes the old content and then uses innerHTML to inject the new content. However, script blocks contained in the AJAX response do not get executed when added to the page with innerHTML. One way to get things working is to execute them using them with the eval() method. Another way is to manually construct a script object and add it to the head of the page. Either way, to get things working one needs to parse the AJAX response stream for script tags, extract their contents and force the browser to parse the scripts.

One way to workaround the problem is to take the approach of RadScriptBlock which comes with Telerik RadControls. What it does essentially is register its content (which is supposed to be a script tag) with the script manager, e.g.:

 

   <telerik:MyScriptBlock runat="server"
 
            <script type="text/javascript"
 
                alert("I can run with AJAX"); 
 
            </script> 
 
        </telerik:MyScriptBlock> 

 

And here is a possible implementation of such a control:

 

public class MyScriptBlock : Control { 
 
    protected override void Render(HtmlTextWriter writer) 
    { 
        ScriptManager sm = ScriptManager.GetCurrent(Page); 
        StringBuilder sb = new StringBuilder(); 
        base.Render(new HtmlTextWriter(new StringWriter(sb))); 
        string script = sb.ToString(); 
        ScriptManager.RegisterStartupScript(thistypeof(InlineScript), UniqueID, script, false); 
 
    } 

 

While this approach is simple and works real well, it still requires changing your existing controls  - and wrapping their script tags. Yet, could there be a way to avoid any changes to all those tens or hundreds of .ascx-es that you already have in the application you are trying to AJAXify? In fact there is  - and the approach is somewhat similar to what RadAjax does. A simple script added to the main page can take care of this. By using this script, absolutely no changes are required to the original source code of your pages and user controls that use scripts tags and are loaded through AJAX.

The example features a user control with inline script. There three scenarios demonstrated – a simple postback (as the base case), MS AJAX load (not working OK), and the properly working solution using the above-mentioned script.

What the script does is getting the response text of the AJAX request and extracting the script blocks’ content from it. After that a script element is dynamically created by using the document.createElement(“script”) method, the extracted script content is assigned to it and the new generated script block is added to the DOM.

Attached to this post is a fully functional demo.

.UserControlWithScriptAndAjax (1)

10 Comments

  • Matthew Phillips 09 Feb 2009
    What do I do with a .SFLB file?
    I can't see your example!
    cheers
    Matt
  • Visitor 23 Feb 2009
    It is in fact a .zip file.
    When you download it, change its extension to .zip and you should be fine.
  • Al Shenker 16 Jul 2009
    Is there any way to implement this without either of the two conditions as described in the following support thread..

    http://www.telerik.com/account/support-tickets/view-ticket.aspx?threadid=195160

    Option A, Setting the AjaxManager.RestoreOriginalRenderDelegate property to false

    Option B, inheriting from RadajaxPage isntead of Page.

    As I mentioned in the thread, these are pretty limiting options, considering the fact that medium trust level environments (most shared hosting accounts and an ever-increasing number of dedicated hosting accounts) preclude using Option A, and,

    having to change the page inheritance structure to a Telerik-specific base-class may not be possible when business rules require the use of a custom base class that isn't dependent on Telerik.
  • Lyudmil 11 Aug 2009
    Hi.

    When I try the Java Script shown in the example I receive the following error(using Firebug):

    args.get_response()._xmlHttpRequest has no properties.

    Any suggestions how to solve this?
  • Lyudmil 11 Aug 2009
    Hi.

    When I try the Java Script shown in the example I receive the following error(using Firebug):

    args.get_response()._xmlHttpRequest has no properties.

    Any suggestions how to solve this?
  • NNM 09 Sep 2009
    Same here, just js error on the same line as above post...
    After all the attempts at this, I'm starting to think this is a hoax.. lol

  • Zeke Sheppard 17 Feb 2010
    Getting args.get_response()._xmlHttpRequest has no properties. Any resolution to this?
  • Svetlina 26 Feb 2010

    Hello guys,

    The provided workaround solves a general problem related to MS AJAX and it works in most of the cases except for some scenarios which are more complex. One possible solution which can be used in such scenarios is to register the client script from the server e.g as shown below:


    UserControl.ascx:


    <asp:Button ID="btn" runat="server" OnClientClick="InternalCall();return false;" 
     Text="Test" /> 



    UserControl.ascx.cs:

     
    protected void Page_Load(object sender, EventArgs e)  
     {  
      if (Session["registered"] == null)  
      {  
       ScriptManager.RegisterClientScriptBlock(this, GetType(), "btnClick", @"
     function InternalCall() {alert('Javascript declared directly in the user control called form " + btn.ClientID + "');}"true);  
       Session["registered"] = true;  
      }  
     } 
  • Zeke Sheppard 01 Mar 2010
    This sample does not dynamically load a user controls. This is the original issue. Once again you appear to be incapable of delivering a satisfactory response for anything but the simpliest implementations. Nice job, Telerik!
  • Svetlina 04 Mar 2010
    I am not completly sure what exactly you mean by "This sample does not dynamically load a user controls." - the code I provided registers a client script block in the load event and it is fired no matter how you put the user control - dynamically or static. You can test this by loading the user control dynamically with the LoadControl method exactly as I have done in the demo I prepared and provided in your forum thread.

Add comment

  1. Formatting options
       
     
     
     
     
       
  2. (optional, emails won't be shown on public pages)
  3. (optional)