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






3.29/5 (5投票s)
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 解决了我在优化流量时替换响应上下文的问题!