2010-10-07 23 views
1

J'ai écrit un contrôle simple, qui implémente ScriptControl. C'est titulaire pour cadre JQuery:Sortie ASP.NET ScriptManager non incluse dans le cache partiel ASP.NET (ascx)

/// <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 + "&"); 
    } 
} 

Je le place à la page en ascx contrôle: Page: `<% @ Page Language = "C#" AutoEventWireup = "true" behind = "p2.aspx.cs" = hérite "LWM.Implementation.Portal.Sample.TestOutputCache.p2" %>

<% @ Register TagPrefix = "LWM" = Src "~/échantillon/TestOutputCache/testControl2.ascx" TagName = "TestControl2" % >

<LWM:TestControl2 ID="testCached" runat="server" /> 


</div> 
</form> 

`

ascx:` <% @ Control Language = "C#" AutoEventWireup = "true" behind = "testControl2.ascx.cs" Inherits = "LWM.Implementation.Portal. Sample.testControl2 "%> <% @ OutputCache Durée =" 600 "VaryByParam =" Aucun "%> % @ Registre TagPrefix =" Controls "Assembly =" LWM.Implementation.Controls "Namespace =" LWM.Implementation.Controls .JQComposite "%> Test 2 fonction (evt) {

 console.log("afterInit 2"); 
    } 
</AfterInit> 

`

i permettent également de cache contrôle ascx. Lorsque la page est chargée pour la première fois tout est ok, mais quand la page est gérée depuis le cache du serveur toutes les références de script sont manquantes ...

Je recherche beaucoup et aucune idée pour le moment. Donc, le problème est que scriptmanager ne génère pas de référence de script lorsque le contrôle est chargé à partir du cache du serveur.

Répondre

1

Ceci est bogue avec OutputCaching et Gestionnaire de scripts, qui a été officiellement recognized by Microsoft

Il y a solution pour ajouter des scripts à ScriptManager manuellement:

<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> 
+0

Le lien Microsoft semble être cassé ou permission refusée. –