ASP.NET ScriptManager 输出未包含在 ASP.NET 部分缓存 (ascx) 中
我编写了一个简单控件,它实现了 ScriptControl。这是 JQuery 框架的持有者:
/// <summary>
/// Generic control with client behavior handled via jQuery
/// </summary>
public abstract partial class JQControl : ScriptControl, INamingContainer
{
/// <summary>
/// Client method to be called after jQuery initialization
/// </summary>
[PersistenceMode(PersistenceMode.InnerProperty)]
public JQRaw AfterInit
{
get;
set;
}
/// <summary>
/// Client method to be called before jQuery initialization
/// </summary>
[PersistenceMode(PersistenceMode.InnerProperty)]
public JQRaw PreInit
{
get;
set;
}
/// <summary>
/// Any data to initialize the control with (name-value pairs)
/// </summary>
public IDictionary<string, object> InitData
{
get; set;
}
/// <summary>
/// Authorization templates to be registered and used by privilege manager
/// </summary>
public IDictionary<string, AuthorizationTemplate> AuthorizationTemplates
{
get; set;
}
/// <summary>
/// If ThemePath is specified, this css file will be looked for and loaded from the theme folder
/// </summary>
protected string ThemeCssName
{
get; set;
}
private string _themePath;
/// <summary>
/// Specifies path to look for custom css and images to enable theming.
/// </summary>
public string ThemePath
{
get
{
return _themePath == null ? DefaultThemeHelper.ThemeName : ResolveClientUrl(_themePath);
}
set
{
_themePath = value;
}
}
/// <summary>
/// Collection of streamed javascript files
/// </summary>
private readonly List<ScriptReference> scriptRefs = new List<ScriptReference>();
/// <summary>
/// Collection of streamed stylesheet files
/// </summary>
private readonly List<string> cssRefs = new List<string>();
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
FillScriptReferences();
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
}
protected bool useDynamicCss = true;
private bool dynamicCssEnabled;
protected void EnableDynamicCss()
{
if(!dynamicCssEnabled)
{
//enable dynamic css loading
addScriptReference(typeof(JQControl), "LWM.Implementation.Controls.DynamicStylesheet.css.js");
dynamicCssEnabled = true;
}
}
protected virtual void FillScriptReferences()
{
Type t = typeof(JQControl);
addScriptReference(t, "LWM.Implementation.Controls.JScripts.Jquery.js");
addScriptReference(t, "LWM.Implementation.Controls.JScripts.ExtendJQuery.js");
addScriptReference(t, "LWM.Implementation.Controls.JScripts.ExtendAJAXDotNet.js");
addScriptReference(t, "LWM.Implementation.Controls.JQ.ChainRequests.js");
addScriptReference(t, "LWM.Implementation.Controls.JScripts.jquery.jcache.js");
addScriptReference(t, "LWM.Implementation.Controls.JScripts.jquery.cookie.js");
addScriptReference(t, "LWM.Implementation.Controls.JScripts.jquery.offset.js");
//if ((_themePath != null && ThemeCssName != null))
{
EnableDynamicCss();
}
}
//added to render automatically assigned id, otherwise escaped
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
const string extCss = "jqcontrol";
this.CssClass = this.CssClass != null ? this.CssClass + " " + extCss : extCss;
base.AddAttributesToRender(writer);
writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
//writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass);
}
/// <summary>
/// Ataches an embedded script refernnce using its full name
/// </summary>
/// <param name="name">Name of the reference</param>
/// <param name="useBaseClassAssembly">True if using base class assembly</param>
protected void AttachScriptRefernceByName(string name, bool useBaseClassAssembly)
{
//current type
Type type = this.GetType();
if (useBaseClassAssembly)
{
//base type
type = type.BaseType;
}
addScriptReference(type, name);
}
private void _addCssReference(Type type, string name)
{
string assembly = type.Assembly.FullName;
Type t = null;
if (BoostHelper.AdjustResourceParts(this, type.Assembly, ref assembly, ref name, ref t))
{
// LoggerHelper.LogInfo(String.Format("CSS init with- Client Script:{0}, Type:{1}, Name:{2} ", this.Page.ClientScript.ToString(),t.ToString(),name),"LWMSiteResourceBooster");
var sr = new DynamicStylesheetScriptReference(this.Page.ClientScript, t, new[] { name }); //(name, assembly);
if (!scriptRefs.Contains(sr))
{
scriptRefs.Add(sr);
}
}
else
{
string url = name; // GetEmbeddedURL(type, name);
if (!cssRefs.Contains(url))
{
cssRefs.Add(url);
}
}
}
//protected void addCssReference(string name, Type type)
//{
// _addCssReference(type, name);
// if (cssRefs.Count > 0)
// {
// scriptRefs.Add(new DynamicStylesheetScriptReference(this.Page.ClientScript, type, cssRefs.ToArray()));
// cssRefs.Clear();
// }
//}
protected void addCssReference(Type type, params string[] names)
{
if (names == null) return;
foreach (string name in names)
{
_addCssReference(type, name);
}
if(cssRefs.Count > 0)
{
scriptRefs.Add(new DynamicStylesheetScriptReference(this.Page.ClientScript, type, cssRefs.ToArray()));
cssRefs.Clear();
}
}
protected void removeCssReference(Type type, string name)
{
//TODO
//if (cssRefs.Contains(url))
//{
// cssRefs.Remove(url);
//}
}
protected void addScriptReference(Type type, string name)
{
//full name of the current assembly
string assembly = type.Assembly.FullName;
Type t = null;
BoostHelper.AdjustResourceParts(this, type.Assembly, ref assembly, ref name, ref t);
var sr = new HumanReadableScriptReference(name, assembly);
if (!scriptRefs.Contains(sr))
{
scriptRefs.Add(sr);
}
}
protected void removeScriptReference(Type type, string name)
{
//full name of the current assembly
string assembly = type.Assembly.FullName;
Type t = null;
BoostHelper.AdjustResourceParts(this, type.Assembly, ref assembly, ref name, ref t);
var sr = new HumanReadableScriptReference(name, assembly);
if (scriptRefs.Contains(sr))
{
scriptRefs.Remove(sr);
}
}
private string _jqBreadCrumb;
/// <summary>
/// Unique jQuery pattern that identifies this control
/// </summary>
protected string JQBreadCrumb
{
get
{
if (_jqBreadCrumb == null)
{
//StringBuilder sb = new StringBuilder();
//Control c = this;
Control c = this.NamingContainer;
//int step = 1;
while (c != null && c.ClientID != "__Page")
{
if (c is JQControl) // || step > 1)
{
_jqBreadCrumb = c.ClientID;
break;
//sb.Insert(0, " ");
//sb.Insert(0, "#" + c.ClientID);
}
c = c.NamingContainer;
//step++;
}
//_jqBreadCrumb = sb.ToString();
}
return _jqBreadCrumb;
}
}
//regular expression to look for tokens
private static readonly Regex tokenRegex = new Regex(
@"##(?<tokenName>[\w\:]+)"
);
//actually replaces tokens
private string tokenReplacer(Match m, bool useContext)
{
//token found
string tokenName = m.Groups["tokenName"].Value;
string ctlName = null;
//check if we have a resource token
if (ResourceHelper.CheckStringForToken(tokenName))
{
return "\"" + ResourceHelper.GetStringByToken(tokenName, ResourceType.Portal) + "\"";
}
switch (tokenName)
{
case "this":
//special case: seek for the current control
if (useContext) return "$(__$)";
ctlName = "#" + this.ClientID; // JQBreadCrumb;
break;
case "parent":
//special case: seek for the direct parent control
ctlName = "#" + JQBreadCrumb;
// this.NamingContainer.ClientID; //NOTE: use parent breadcrumb here
break;
default:
//seek for the child control with the given name
if (!useContext)
{
Control ctl = getChildByName(tokenName);
if (ctl != null) ctlName = "#" + ctl.ClientID;
}
//else ctlName = "[id^='" + this.ClientID + "_']" + "[id$='_" + tokenName + "']:first";
break;
}
if(ctlName != null) return "$(\"" + ctlName + "\")";
if (!useContext) return "$(this)._cc('" + tokenName + "', '" + this.ClientID + "')";
return "$(__$)._cc('" + tokenName + "')";
}
private string tokenReplacerWithContext(Match m)
{
return tokenReplacer(m, true);
}
private string tokenReplacerWithoutContext(Match m)
{
return tokenReplacer(m, false);
}
protected virtual Control getChildByName(string name)
{
return this.Controls.Cast<Control>().SingleOrDefault(c => c.ID == name);
}
//regular expression to insert context holder
private static readonly Regex contextRegex = new Regex(
@"^(\s*function\(\s*\)\s*{)", RegexOptions.Multiline
);
private static int replacedNum;
private static string contextReplacer(Match m)
{
replacedNum++;
return "function() { var __$ = this; \r\n";
}
/// <summary>
/// Substitue occurences of tokens of type ##[token] into corresponding jQuery calls
/// </summary>
/// <param name="callbackMethod">Callback method definition that contains tokens</param>
/// <param name="useContext">True if local context is to be used on the client</param>
protected void PrepareCallbackMethod(JQRaw callbackMethod, bool useContext)
{
if(useContext)
{
replacedNum = 0;
callbackMethod.JQRawContent = contextRegex.Replace(callbackMethod.JQRawContent, contextReplacer);
if(replacedNum == 0) useContext = false;
}
if (callbackMethod != null)
{
MatchEvaluator me;
if(useContext) me = tokenReplacerWithContext;
else me = tokenReplacerWithoutContext;
//find tokens in callback body and replace them
callbackMethod.JQRawContent = tokenRegex.Replace(callbackMethod.JQRawContent, me);
}
}
protected void PrepareCallbackMethod(JQRaw callbackMethod)
{
PrepareCallbackMethod(callbackMethod, false);
}
protected virtual void PrepareCallbackMethods(object @params)
{
foreach (PropertyInfo pi in @params.GetType().GetProperties().Where(
p => p.PropertyType.Equals(typeof(JQRaw))
))
{
if (pi.GetCustomAttributes(typeof(CallbackMethodAttribute), false).Length > 0)
{
//property has the attribute: prepare
JQRaw pty = (JQRaw)pi.GetValue(@params, null);
if (pty != null && pty.JQRawContent != null)
{
PrepareCallbackMethod(pty);
}
}
}
}
/// <summary>
/// Returns the script files for the control
/// </summary>
/// <returns>Collection that contains ECMAScript (JavaScript) files that have been registered as embedded resources</returns>
protected override IEnumerable<ScriptReference> GetScriptReferences()
{
return scriptRefs;
}
private const string selfAlias = "__$";
protected virtual string GetDescriptorSelector()
{
//return this.ClientID;
return selfAlias;
}
protected virtual IEnumerable<ScriptDescriptor> _getScriptDescriptors()
{
yield break;
}
//private const string afterInitTemplate = "function() {{ var _method = {0}; _method(); $('#{1}').trigger('_loadComplete'); }}";
protected sealed override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
{
var result = new List<ScriptDescriptor>();
//yield return new JQSelfDescriptor(this.ClientID, selfAlias);
result.Add(new JQSelfDescriptor(this.ClientID, selfAlias));
if (PreInit != null)
{
//to be executed before initialization
PrepareCallbackMethod(PreInit, true);
//yield return new JQDescriptor(GetDescriptorSelector(), "each", true, PreInit);
result.Add(new JQDescriptor(GetDescriptorSelector(), "each", true, PreInit));
}
if(InitData != null)
{
foreach (string key in InitData.Keys)
{
//initialize with the given object as data
object data;
bool useStd = false;
if (InitData[key] is NativeContainer)
{
data = ((NativeContainer)InitData[key]).Content;
useStd = true;
}
else data = InitData[key];
JQDescriptor jdesc = new JQDescriptor(GetDescriptorSelector(), "data", true, key, data);
if(useStd) jdesc.UseStandardSerializer = true;
//yield return jdesc;
result.Add(jdesc);
}
}
if (AuthorizationTemplates != null)
{
//register authorization templates
//yield return new JQDescriptor(GetDescriptorSelector(), "pm_registerAuthTemplates", true, AuthorizationTemplates);
result.Add(new JQDescriptor(GetDescriptorSelector(), "pm_registerAuthTemplates", true, AuthorizationTemplates));
}
//enumerate overriden method results
foreach(ScriptDescriptor sd in _getScriptDescriptors())
{
// yield return sd;
result.Add(sd);
}
if (AfterInit != null)
{
//to be executed after initialization
PrepareCallbackMethod(AfterInit, true);
//AfterInit.JQRawContent = String.Format(afterInitTemplate, AfterInit.JQRawContent, GetDescriptorSelector());
//yield return new JQDescriptor(GetDescriptorSelector(), "each", true, AfterInit);
result.Add(new JQDescriptor(GetDescriptorSelector(), "each", true, AfterInit));
}
if (ThemePath != null && ThemeCssName != null)
{
//load css file dynamically
string cssURL = VirtualURLHelper.Combine(ThemePath, ThemeCssName);
DynamicStylesheetDescriptor dsdesc = new DynamicStylesheetDescriptor(cssURL);
//yield return dsdesc;
result.Add(dsdesc);
}
if (cssRefs.Count > 0)
{
DynamicStylesheetDescriptor dsdesc = new DynamicStylesheetDescriptor(cssRefs);
//yield return dsdesc;
result.Add(dsdesc);
}
//final trigger
//yield return new JQDescriptor(GetDescriptorSelector(), "trigger", "_loadComplete");
//yield break;
return result;
}
/// <summary>
/// Helper method to create URL to an embedded resource
/// </summary>
/// <param name="type">The type of the server-side resource</param>
/// <param name="resourceName">The name of the server-side resource</param>
/// <returns>The URL reference to the resource</returns>
protected string GetEmbeddedURL(Type type, string resourceName)
{
//get base URL
string url = Page.ClientScript.GetWebResourceUrl(type, resourceName);
//attach name of the resource
return url.Replace("?", "?name=" + resourceName + "&");
}
}
我将其放在 ascx Control 的页面上: 页面: `<%@ 页面语言=“C#” AutoEventWireup=“true” CodeBehind=“p2.aspx.cs” Inherits=“LWM.Implementation.Portal.Sample.TestOutputCache.p2” %>
<%@ Register TagPrefix="LWM" Src="~/Sample/TestOutputCache/testControl2.ascx" TagName="TestControl2"%>
<LWM:TestControl2 ID="testCached" runat="server" />
</div>
</form>
`
ascx: `<%@ 控制语言="C#" AutoEventWireup="true" CodeBehind="testControl2.ascx.cs" Inherits="LWM.Implementation.Portal.Sample.testControl2" %> <%@ OutputCache Duration="600" VaryByParam="无" %> <%@ Register TagPrefix="Controls" Assembly="LWM.Implementation.Controls" Namespace="LWM.Implementation.Controls.JQComposite" %> 测试2 函数(事件) {
console.log("afterInit 2");
}
</AfterInit>
`
我还启用了 ascx 控制缓存。当页面首次加载时一切正常,但是当从服务器缓存获取页面时,所有脚本引用都丢失了......
我搜索了很多,但找不到任何想法。 因此,问题是当从服务器缓存加载控件时,脚本管理器不会生成脚本引用。
I wrote a Simple Control, that implements ScriptControl. This is holder for JQuery framework:
/// <summary>
/// Generic control with client behavior handled via jQuery
/// </summary>
public abstract partial class JQControl : ScriptControl, INamingContainer
{
/// <summary>
/// Client method to be called after jQuery initialization
/// </summary>
[PersistenceMode(PersistenceMode.InnerProperty)]
public JQRaw AfterInit
{
get;
set;
}
/// <summary>
/// Client method to be called before jQuery initialization
/// </summary>
[PersistenceMode(PersistenceMode.InnerProperty)]
public JQRaw PreInit
{
get;
set;
}
/// <summary>
/// Any data to initialize the control with (name-value pairs)
/// </summary>
public IDictionary<string, object> InitData
{
get; set;
}
/// <summary>
/// Authorization templates to be registered and used by privilege manager
/// </summary>
public IDictionary<string, AuthorizationTemplate> AuthorizationTemplates
{
get; set;
}
/// <summary>
/// If ThemePath is specified, this css file will be looked for and loaded from the theme folder
/// </summary>
protected string ThemeCssName
{
get; set;
}
private string _themePath;
/// <summary>
/// Specifies path to look for custom css and images to enable theming.
/// </summary>
public string ThemePath
{
get
{
return _themePath == null ? DefaultThemeHelper.ThemeName : ResolveClientUrl(_themePath);
}
set
{
_themePath = value;
}
}
/// <summary>
/// Collection of streamed javascript files
/// </summary>
private readonly List<ScriptReference> scriptRefs = new List<ScriptReference>();
/// <summary>
/// Collection of streamed stylesheet files
/// </summary>
private readonly List<string> cssRefs = new List<string>();
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
FillScriptReferences();
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
}
protected bool useDynamicCss = true;
private bool dynamicCssEnabled;
protected void EnableDynamicCss()
{
if(!dynamicCssEnabled)
{
//enable dynamic css loading
addScriptReference(typeof(JQControl), "LWM.Implementation.Controls.DynamicStylesheet.css.js");
dynamicCssEnabled = true;
}
}
protected virtual void FillScriptReferences()
{
Type t = typeof(JQControl);
addScriptReference(t, "LWM.Implementation.Controls.JScripts.Jquery.js");
addScriptReference(t, "LWM.Implementation.Controls.JScripts.ExtendJQuery.js");
addScriptReference(t, "LWM.Implementation.Controls.JScripts.ExtendAJAXDotNet.js");
addScriptReference(t, "LWM.Implementation.Controls.JQ.ChainRequests.js");
addScriptReference(t, "LWM.Implementation.Controls.JScripts.jquery.jcache.js");
addScriptReference(t, "LWM.Implementation.Controls.JScripts.jquery.cookie.js");
addScriptReference(t, "LWM.Implementation.Controls.JScripts.jquery.offset.js");
//if ((_themePath != null && ThemeCssName != null))
{
EnableDynamicCss();
}
}
//added to render automatically assigned id, otherwise escaped
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
const string extCss = "jqcontrol";
this.CssClass = this.CssClass != null ? this.CssClass + " " + extCss : extCss;
base.AddAttributesToRender(writer);
writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
//writer.AddAttribute(HtmlTextWriterAttribute.Class, CssClass);
}
/// <summary>
/// Ataches an embedded script refernnce using its full name
/// </summary>
/// <param name="name">Name of the reference</param>
/// <param name="useBaseClassAssembly">True if using base class assembly</param>
protected void AttachScriptRefernceByName(string name, bool useBaseClassAssembly)
{
//current type
Type type = this.GetType();
if (useBaseClassAssembly)
{
//base type
type = type.BaseType;
}
addScriptReference(type, name);
}
private void _addCssReference(Type type, string name)
{
string assembly = type.Assembly.FullName;
Type t = null;
if (BoostHelper.AdjustResourceParts(this, type.Assembly, ref assembly, ref name, ref t))
{
// LoggerHelper.LogInfo(String.Format("CSS init with- Client Script:{0}, Type:{1}, Name:{2} ", this.Page.ClientScript.ToString(),t.ToString(),name),"LWMSiteResourceBooster");
var sr = new DynamicStylesheetScriptReference(this.Page.ClientScript, t, new[] { name }); //(name, assembly);
if (!scriptRefs.Contains(sr))
{
scriptRefs.Add(sr);
}
}
else
{
string url = name; // GetEmbeddedURL(type, name);
if (!cssRefs.Contains(url))
{
cssRefs.Add(url);
}
}
}
//protected void addCssReference(string name, Type type)
//{
// _addCssReference(type, name);
// if (cssRefs.Count > 0)
// {
// scriptRefs.Add(new DynamicStylesheetScriptReference(this.Page.ClientScript, type, cssRefs.ToArray()));
// cssRefs.Clear();
// }
//}
protected void addCssReference(Type type, params string[] names)
{
if (names == null) return;
foreach (string name in names)
{
_addCssReference(type, name);
}
if(cssRefs.Count > 0)
{
scriptRefs.Add(new DynamicStylesheetScriptReference(this.Page.ClientScript, type, cssRefs.ToArray()));
cssRefs.Clear();
}
}
protected void removeCssReference(Type type, string name)
{
//TODO
//if (cssRefs.Contains(url))
//{
// cssRefs.Remove(url);
//}
}
protected void addScriptReference(Type type, string name)
{
//full name of the current assembly
string assembly = type.Assembly.FullName;
Type t = null;
BoostHelper.AdjustResourceParts(this, type.Assembly, ref assembly, ref name, ref t);
var sr = new HumanReadableScriptReference(name, assembly);
if (!scriptRefs.Contains(sr))
{
scriptRefs.Add(sr);
}
}
protected void removeScriptReference(Type type, string name)
{
//full name of the current assembly
string assembly = type.Assembly.FullName;
Type t = null;
BoostHelper.AdjustResourceParts(this, type.Assembly, ref assembly, ref name, ref t);
var sr = new HumanReadableScriptReference(name, assembly);
if (scriptRefs.Contains(sr))
{
scriptRefs.Remove(sr);
}
}
private string _jqBreadCrumb;
/// <summary>
/// Unique jQuery pattern that identifies this control
/// </summary>
protected string JQBreadCrumb
{
get
{
if (_jqBreadCrumb == null)
{
//StringBuilder sb = new StringBuilder();
//Control c = this;
Control c = this.NamingContainer;
//int step = 1;
while (c != null && c.ClientID != "__Page")
{
if (c is JQControl) // || step > 1)
{
_jqBreadCrumb = c.ClientID;
break;
//sb.Insert(0, " ");
//sb.Insert(0, "#" + c.ClientID);
}
c = c.NamingContainer;
//step++;
}
//_jqBreadCrumb = sb.ToString();
}
return _jqBreadCrumb;
}
}
//regular expression to look for tokens
private static readonly Regex tokenRegex = new Regex(
@"##(?<tokenName>[\w\:]+)"
);
//actually replaces tokens
private string tokenReplacer(Match m, bool useContext)
{
//token found
string tokenName = m.Groups["tokenName"].Value;
string ctlName = null;
//check if we have a resource token
if (ResourceHelper.CheckStringForToken(tokenName))
{
return "\"" + ResourceHelper.GetStringByToken(tokenName, ResourceType.Portal) + "\"";
}
switch (tokenName)
{
case "this":
//special case: seek for the current control
if (useContext) return "$(__$)";
ctlName = "#" + this.ClientID; // JQBreadCrumb;
break;
case "parent":
//special case: seek for the direct parent control
ctlName = "#" + JQBreadCrumb;
// this.NamingContainer.ClientID; //NOTE: use parent breadcrumb here
break;
default:
//seek for the child control with the given name
if (!useContext)
{
Control ctl = getChildByName(tokenName);
if (ctl != null) ctlName = "#" + ctl.ClientID;
}
//else ctlName = "[id^='" + this.ClientID + "_']" + "[id$='_" + tokenName + "']:first";
break;
}
if(ctlName != null) return "$(\"" + ctlName + "\")";
if (!useContext) return "$(this)._cc('" + tokenName + "', '" + this.ClientID + "')";
return "$(__$)._cc('" + tokenName + "')";
}
private string tokenReplacerWithContext(Match m)
{
return tokenReplacer(m, true);
}
private string tokenReplacerWithoutContext(Match m)
{
return tokenReplacer(m, false);
}
protected virtual Control getChildByName(string name)
{
return this.Controls.Cast<Control>().SingleOrDefault(c => c.ID == name);
}
//regular expression to insert context holder
private static readonly Regex contextRegex = new Regex(
@"^(\s*function\(\s*\)\s*{)", RegexOptions.Multiline
);
private static int replacedNum;
private static string contextReplacer(Match m)
{
replacedNum++;
return "function() { var __$ = this; \r\n";
}
/// <summary>
/// Substitue occurences of tokens of type ##[token] into corresponding jQuery calls
/// </summary>
/// <param name="callbackMethod">Callback method definition that contains tokens</param>
/// <param name="useContext">True if local context is to be used on the client</param>
protected void PrepareCallbackMethod(JQRaw callbackMethod, bool useContext)
{
if(useContext)
{
replacedNum = 0;
callbackMethod.JQRawContent = contextRegex.Replace(callbackMethod.JQRawContent, contextReplacer);
if(replacedNum == 0) useContext = false;
}
if (callbackMethod != null)
{
MatchEvaluator me;
if(useContext) me = tokenReplacerWithContext;
else me = tokenReplacerWithoutContext;
//find tokens in callback body and replace them
callbackMethod.JQRawContent = tokenRegex.Replace(callbackMethod.JQRawContent, me);
}
}
protected void PrepareCallbackMethod(JQRaw callbackMethod)
{
PrepareCallbackMethod(callbackMethod, false);
}
protected virtual void PrepareCallbackMethods(object @params)
{
foreach (PropertyInfo pi in @params.GetType().GetProperties().Where(
p => p.PropertyType.Equals(typeof(JQRaw))
))
{
if (pi.GetCustomAttributes(typeof(CallbackMethodAttribute), false).Length > 0)
{
//property has the attribute: prepare
JQRaw pty = (JQRaw)pi.GetValue(@params, null);
if (pty != null && pty.JQRawContent != null)
{
PrepareCallbackMethod(pty);
}
}
}
}
/// <summary>
/// Returns the script files for the control
/// </summary>
/// <returns>Collection that contains ECMAScript (JavaScript) files that have been registered as embedded resources</returns>
protected override IEnumerable<ScriptReference> GetScriptReferences()
{
return scriptRefs;
}
private const string selfAlias = "__$";
protected virtual string GetDescriptorSelector()
{
//return this.ClientID;
return selfAlias;
}
protected virtual IEnumerable<ScriptDescriptor> _getScriptDescriptors()
{
yield break;
}
//private const string afterInitTemplate = "function() {{ var _method = {0}; _method(); $('#{1}').trigger('_loadComplete'); }}";
protected sealed override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
{
var result = new List<ScriptDescriptor>();
//yield return new JQSelfDescriptor(this.ClientID, selfAlias);
result.Add(new JQSelfDescriptor(this.ClientID, selfAlias));
if (PreInit != null)
{
//to be executed before initialization
PrepareCallbackMethod(PreInit, true);
//yield return new JQDescriptor(GetDescriptorSelector(), "each", true, PreInit);
result.Add(new JQDescriptor(GetDescriptorSelector(), "each", true, PreInit));
}
if(InitData != null)
{
foreach (string key in InitData.Keys)
{
//initialize with the given object as data
object data;
bool useStd = false;
if (InitData[key] is NativeContainer)
{
data = ((NativeContainer)InitData[key]).Content;
useStd = true;
}
else data = InitData[key];
JQDescriptor jdesc = new JQDescriptor(GetDescriptorSelector(), "data", true, key, data);
if(useStd) jdesc.UseStandardSerializer = true;
//yield return jdesc;
result.Add(jdesc);
}
}
if (AuthorizationTemplates != null)
{
//register authorization templates
//yield return new JQDescriptor(GetDescriptorSelector(), "pm_registerAuthTemplates", true, AuthorizationTemplates);
result.Add(new JQDescriptor(GetDescriptorSelector(), "pm_registerAuthTemplates", true, AuthorizationTemplates));
}
//enumerate overriden method results
foreach(ScriptDescriptor sd in _getScriptDescriptors())
{
// yield return sd;
result.Add(sd);
}
if (AfterInit != null)
{
//to be executed after initialization
PrepareCallbackMethod(AfterInit, true);
//AfterInit.JQRawContent = String.Format(afterInitTemplate, AfterInit.JQRawContent, GetDescriptorSelector());
//yield return new JQDescriptor(GetDescriptorSelector(), "each", true, AfterInit);
result.Add(new JQDescriptor(GetDescriptorSelector(), "each", true, AfterInit));
}
if (ThemePath != null && ThemeCssName != null)
{
//load css file dynamically
string cssURL = VirtualURLHelper.Combine(ThemePath, ThemeCssName);
DynamicStylesheetDescriptor dsdesc = new DynamicStylesheetDescriptor(cssURL);
//yield return dsdesc;
result.Add(dsdesc);
}
if (cssRefs.Count > 0)
{
DynamicStylesheetDescriptor dsdesc = new DynamicStylesheetDescriptor(cssRefs);
//yield return dsdesc;
result.Add(dsdesc);
}
//final trigger
//yield return new JQDescriptor(GetDescriptorSelector(), "trigger", "_loadComplete");
//yield break;
return result;
}
/// <summary>
/// Helper method to create URL to an embedded resource
/// </summary>
/// <param name="type">The type of the server-side resource</param>
/// <param name="resourceName">The name of the server-side resource</param>
/// <returns>The URL reference to the resource</returns>
protected string GetEmbeddedURL(Type type, string resourceName)
{
//get base URL
string url = Page.ClientScript.GetWebResourceUrl(type, resourceName);
//attach name of the resource
return url.Replace("?", "?name=" + resourceName + "&");
}
}
I place it on page into ascx Control:
Page: `<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="p2.aspx.cs" Inherits="LWM.Implementation.Portal.Sample.TestOutputCache.p2" %>
<%@ Register TagPrefix="LWM" Src="~/Sample/TestOutputCache/testControl2.ascx" TagName="TestControl2"%>
<LWM:TestControl2 ID="testCached" runat="server" />
</div>
</form>
`
ascx: `<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="testControl2.ascx.cs"
Inherits="LWM.Implementation.Portal.Sample.testControl2" %>
<%@ OutputCache Duration="600" VaryByParam="None" %>
<%@ Register TagPrefix="Controls" Assembly="LWM.Implementation.Controls" Namespace="LWM.Implementation.Controls.JQComposite" %>
Test 2
function (evt)
{
console.log("afterInit 2");
}
</AfterInit>
`
Also i enable ascx control cache. When page first loaded all ok, but when page getted from server cache all script references are missing...
I search a lot and can't find any idea.
So, problem is that scriptmanager do not generate script reference when control loaded from server cache.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是 OutputCaching 和脚本管理器的错误,官方是 被 Microsoft 认可
有一种解决方法可以手动将脚本添加到 scriptmanager:
This is bug with OutputCaching and Script Manager, which officially was recognized by Microsoft
There is workaround to add scripts to scriptmanager manually: