65.9K
CodeProject 正在变化。 阅读更多。
Home

AJAX UpdatePanel 带有内联客户端脚本解析器

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.29/5 (5投票s)

2007年12月9日

CPOL
viewsIcon

62869

AJAX UpdatePanel 与内联客户端脚本解析器。

引言

此控件解决了在 ASP.NET UpdatePanel 中使用内联客户端脚本时遇到的问题。据我所知,内联脚本在进行“AJAX 调用”时不会注册到 Script Manager。如果有一个 UserControl,其中包含一个内联脚本,该脚本在 AJAX 回发后动态添加到 UpdatePanel 中,就会出现这个问题。

背景

如果您像我一样,已经拥有一个充斥着内联脚本的现有 Web 应用程序,并且希望利用 ASP.NET AJAX 提供的功能,您可能会发现自己面临着繁琐的重构工作。我通过使用此控件成功解决了 99%(1% 是无效的标记)的内联脚本问题。

希望它也能为您做到同样!

Using the Code

该控件继承自原始的 UpdatePanel,并使用 Regex 来解析客户端脚本。您可以使用它就像使用原始的 UpdatePanel 一样,并且可以通过将属性 RegisterInlineClientScripts 设置为 false 来打开/关闭内联脚本的解析。

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);
    }
}
}

欢迎提出优化建议!

尽情享用!

感谢 Rogic 解决了我在优化流量时替换响应上下文的问题!

© . All rights reserved.