Click here to Skip to main content
15,867,568 members
Articles / Web Development / XHTML
Article

AJAX UpdatePanel With Inline Client Scripts Parser

Rate me:
Please Sign up or sign in to vote.
3.29/5 (5 votes)
9 Oct 2008CPOL 60.4K   24   8
AJAX UpdatePanel with inline client scripts parser.

Introduction

This control solves the problem when you need inline client scripts within an ASP.NET UpdatePanel to work. Inline scripts, to my knowledge, are not registered to the Script Manager when the "AJAX call" is made. The problem occurs if you have a UserControl, containing an inline script that is dynamically added into an UpdatePanel after an AJAX postback.

Background

If you, like me, already have (had) an existing Web application that's cluttered with inline scripts, and want to take advantage of the features that ASP.NET AJAX provides, you might find yourself with a tedious refactoring job. I managed to solve 99% (1% was invalid markup) of all my inline script problems by using this control.

Hopefully, it can do the same for you!

Using the Code

The control inherits from the original UpdatePanel and uses a Regex to parse for client scripts. You use it just like the original UpdatePanel, and can switch on/off the parsing for inline scripts by setting the property RegisterInlineClientScripts to false.

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Text.RegularExpressions;
using System.IO;

namespace Tuna.Web.Controls
{
public class TunaUpdatePanel : UpdatePanel
{
    private static readonly Regex REGEX_CLIENTSCRIPTS = new Regex(
    "<script\\s((?<aname>[-\\w]+)=[\"'](?<avalue>.*?)[\"']\\s?)*\\s*>(?<script>.*?)</script>",
    RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Compiled |
    RegexOptions.ExplicitCapture);
    private bool m_RegisterInlineClientScripts = true;

    /// <summary>
    /// If the updatepanel shall parse and append inline scripts, default true
    /// </summary>
    public bool RegisterInlineClientScripts
    {
        get
        {
            return this.m_RegisterInlineClientScripts;
        }
        set
        {
            this.m_RegisterInlineClientScripts = value;
        }
    }

    protected virtual string AppendInlineClientScripts(string htmlsource)
    {
        if (this.ContentTemplate != null && htmlsource.IndexOf(
            "<script", StringComparison.CurrentCultureIgnoreCase) > -1)
        {
            MatchCollection matches = REGEX_CLIENTSCRIPTS.Matches(htmlsource);
            if (matches.Count > 0)
            {
                for (int i = 0; i < matches.Count; i++)
                {
                    string script = matches[i].Groups["script"].Value;
                    string scriptID = script.GetHashCode().ToString();
                    string scriptSrc = "";

                    CaptureCollection aname = matches[i].Groups["aname"].Captures;
                    CaptureCollection avalue = matches[i].Groups["avalue"].Captures;
                    for (int u = 0; u < aname.Count; u++)
                    {
                        if (aname[u].Value.IndexOf("src",
                            StringComparison.CurrentCultureIgnoreCase) == 0)
                        {
                            scriptSrc = avalue[u].Value;
                            break;
                        }
                    }

                    if (scriptSrc.Length > 0)
                    {
                        ScriptManager.RegisterClientScriptInclude(this,
                            this.GetType(), scriptID, scriptSrc);
                    }
                    else
                    {
                        ScriptManager.RegisterClientScriptBlock(this, this.GetType(),
                            scriptID, script, true);
                    }

                    htmlsource = htmlsource.Replace(matches[i].Value, "");
                }

            }
        }
        return htmlsource;
    }

    protected override void RenderChildren(HtmlTextWriter writer)
    {
        ScriptManager sm = ScriptManager.GetCurrent(Page);
        if (this.RegisterInlineClientScripts && sm != null && sm.IsInAsyncPostBack)
        {
            using (HtmlTextWriter htmlwriter = new HtmlTextWriter(new StringWriter()))
            {
                base.RenderChildren(htmlwriter);

                string html;
                int outputSize;

                //Get the actual rendering and size
                html = htmlwriter.InnerWriter.ToString();
                outputSize = html.Length;

                //Append inlinescripts and fetch the new markup and size
                html = this.AppendInlineClientScripts(html);
                outputSize -= html.Length;

                //Replace ContentSize if there are any gains
                if (outputSize > 0)
                {
                    html = this.SetOutputContentSize(html, outputSize);
                }

                writer.Write(html);
            }
        }
        else
        {
            base.RenderChildren(writer);
        }
    }

    private string SetOutputContentSize(string html, int difference)
    {
        string[] split = html.Split('|');
        int size = int.Parse(split[0]);
        split[0] = (size - difference).ToString();
        return string.Join("|", split);
    }
}
}

Optimization suggestions are welcome!

Enjoy!

Thanks to Rogic for solving the issue I hade with replacing the response context to opitmize traffic!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Sweden Sweden
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Member 825063916-Mar-14 23:31
Member 825063916-Mar-14 23:31 
GeneralMy vote of 5 Pin
CyberLight28-Aug-12 1:55
CyberLight28-Aug-12 1:55 
Questionthanks Pin
parsamiga31-Oct-11 21:12
parsamiga31-Oct-11 21:12 
GeneralSome improvements Pin
Rogic22-Sep-08 1:37
Rogic22-Sep-08 1:37 
GeneralRe: Some improvements Pin
Baxterboom7-Oct-08 3:00
Baxterboom7-Oct-08 3:00 
GeneralRe: Some improvements [modified] Pin
Baxterboom8-Oct-08 5:34
Baxterboom8-Oct-08 5:34 
AnswerRe: Some improvements Pin
Rogic21-Oct-08 0:49
Rogic21-Oct-08 0:49 
_rendered variable is introduced as a copy from original UpdatePanel (viewed in Reflector). Actually, I didn't investigate why is it needed, I've just copied it.
GeneralSo close..... Pin
Owen3713-Dec-07 7:26
Owen3713-Dec-07 7:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.