c# - ASP.NET ScriptManager output not included in ASP.NET partial cache (ascx) -
i wrote simple control, implements scriptcontrol. holder jquery framework:
/// <summary> /// generic control client behavior handled via jquery /// </summary> public abstract partial class jqcontrol : scriptcontrol, inamingcontainer { /// <summary> /// client method called after jquery initialization /// </summary> [persistencemode(persistencemode.innerproperty)] public jqraw afterinit { get; set; } /// <summary> /// client method called before jquery initialization /// </summary> [persistencemode(persistencemode.innerproperty)] public jqraw preinit { get; set; } /// <summary> /// data initialize control (name-value pairs) /// </summary> public idictionary<string, object> initdata { get; set; } /// <summary> /// authorization templates registered , used privilege manager /// </summary> public idictionary<string, authorizationtemplate> authorizationtemplates { get; set; } /// <summary> /// if themepath specified, css file looked , loaded theme folder /// </summary> protected string themecssname { get; set; } private string _themepath; /// <summary> /// specifies path custom css , images enable theming. /// </summary> public string themepath { { 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 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 embedded script refernnce using full name /// </summary> /// <param name="name">name of 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 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 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 identifies control /// </summary> protected string jqbreadcrumb { { 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 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 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 have resource token if (resourcehelper.checkstringfortoken(tokenname)) { return "\"" + resourcehelper.getstringbytoken(tokenname, resourcetype.portal) + "\""; } switch (tokenname) { case "this": //special case: seek current control if (usecontext) return "$(__$)"; ctlname = "#" + this.clientid; // jqbreadcrumb; break; case "parent": //special case: seek direct parent control ctlname = "#" + jqbreadcrumb; // this.namingcontainer.clientid; //note: use parent breadcrumb here break; default: //seek child control 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 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] corresponding jquery calls /// </summary> /// <param name="callbackmethod">callback method definition contains tokens</param> /// <param name="usecontext">true if local context used on 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 , 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 attribute: prepare jqraw pty = (jqraw)pi.getvalue(@params, null); if (pty != null && pty.jqrawcontent != null) { preparecallbackmethod(pty); } } } } /// <summary> /// returns script files control /// </summary> /// <returns>collection contains ecmascript (javascript) files have been registered 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 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 given object data object data; bool usestd = false; if (initdata[key] 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 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 create url embedded resource /// </summary> /// <param name="type">the type of server-side resource</param> /// <param name="resourcename">the name of server-side resource</param> /// <returns>the url reference resource</returns> protected string getembeddedurl(type type, string resourcename) { //get base url string url = page.clientscript.getwebresourceurl(type, resourcename); //attach name of resource return url.replace("?", "?name=" + resourcename + "&"); } }
i place on page 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 enable ascx control cache. when page first loaded ok, when page getted server cache script references missing...
i search lot , can't find idea. so, problem scriptmanager not generate script reference when control loaded server cache.
this bug outputcaching , script manager, officially recognized microsoft
there workaround add scripts scriptmanager manually:
<asp:scriptmanager id="scriptmanager1" runat="server"> <scripts> <asp:scriptreference name="ajaxcontroltoolkit.common.common.js" assembly="ajaxcontroltoolkit" /> <asp:scriptreference name="ajaxcontroltoolkit.extenderbase.basescripts.js" assembly="ajaxcontroltoolkit" /> <asp:scriptreference name="ajaxcontroltoolkit.textboxwatermark.textboxwatermark.js" assembly="ajaxcontroltoolkit" /> </scripts> </asp:scriptmanager>
Comments
Post a Comment