Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Atteint de JavaScriptite Aiguë [Cyril Durand]

Expert ASP.net Ajax et WCF, Cyril Durand parle dans son blog de point techniques sur ASP.net, ASP.net Ajax, JavaScript, WCF et .net en général. Cyril est également consultant indépendant, n'hésitez pas à le contacter pour de l'assistance sur vos projets

Actualités

  • Blog de Cyril DURAND, passionné de JavaScript, Ajax, ASP.net et tout ce qui touche au developpement Web Client-Side.

    N'hésitez pas à me contacter pour vos projets .net : architecture, accompagnement, formation, ...

    View Cyril Durand's profile on LinkedIn
    hit counters


    Expertise Commerce server et BizTalk

Regrouper plusieurs fichiers javascript grace au ToolkitScriptManager

Depuis quelques temps déjà, les dernières versions des Ajax Control Toolkit intègre un nouveau contrôle qui hérite du ScriptManager : le ToolkitScriptManager. Ce contrôle permet de combiner plusieurs fichiers JavaScript en un seul. Lorsque vous utilisez plusieurs toolkits sur la même page le client doit télécharger de nombreux fichiers JavaScript ce qui entraine des performances plutôt mauvaise. De plus le ToolkitScriptManager permet de compacter et gzipper les fichiers JavaScript. J'en ai aussi parlé ici : Réduire la taille des fichiers JavaScript

Pour le faire fonctionner, il suffit de remplacer le classique ScriptManager par le ToolkitScriptManager.

<ajaxtoolkit:ToolkitScriptManager runat="server" />

Automatiquement, tous les fichiers JavaScript ajoutés par les toolkits seront combinés en un seul. Par défaut l'url du fichier JavaScript final est :

CurrentPage.aspx?_TSM_HiddenField_=ctl00_SampleContent_ScriptManager1_HiddenField&amp;_TSM_...

Oui ! Vous avez bien lu, le fichier résultat pointe sur la page en cours. Cela implique 2 choses :

  • Dès qu'on change de page, le fichier sera différent, il n'y aura aucun cache client pour ce fichier;
  • La page va être exécutée deux fois : Page_Load, ...

Bref, par défaut le comportement est stupide. Heureusement il est possible de spécifier l'adresse d'un handler qui s'occupera de combiner les différents fichiers.

Voici ce que vous pouvez mettre dans un fichier CombineScriptsHandler.ashx afin d'avoir qu'une seule url pour tout le site.

<%@ WebHandler Language="C#" Class="CombineScriptsHandler" %> // CombineScriptsHandler.ashx using System; using System.Web; using AjaxControlToolkit; public class CombineScriptsHandler : IHttpHandler { /// <summary> /// ProcessRequest implementation outputs the combined script file /// </summary> /// <param name="context"></param> public void ProcessRequest(HttpContext context) { if (!ToolkitScriptManager.OutputCombinedScriptFile(context)) { throw new InvalidOperationException("Combined script file output failed unexpectedly."); } } /// <summary> /// IsReusable implementation returns true since this class is stateless /// </summary> public bool IsReusable { get { return true; } } }

Il vous suffit ensuite de renseigner la propriété CombineScriptHandlerUrl du ToolkitScriptManager

<ajaxToolkit:ToolkitScriptManager runat="server" CombineScriptsHandlerUrl="~/CombineScriptsHandler.ashx" />

Astuce : Si vous avez mis le ScriptManager dans toutes vos pages plutôt qu'uniquement dans le masterpage, vous pouvez utiliser du TagMapping pour remplacer tous les ScriptManager par des ToolkitScriptManager et spécifier la propriété CombineScriptsHandlerUrl au niveau du fichier de skin. Pour en savoir plus sur le TagMapping : TagMapping : comment changer les comportements des controles web en quelques lignes

Le mieux reste bien sur de mettre le ScriptManager au niveau du masterpage et si besoin, se servir d'un ScriptManagerProxy dans vos pages pour ajouter des scripts précis.

Jusque là tout va bien, mais malheureusement le contrôle possède un bug. En effet le ScriptManager permet de rajouter des scripts manuellement, je m'en sers souvent pour utiliser les Animations des toolkits sans devoir passer par le contrôle serveur. Pour cela j'utilise un ScriptReference.

<ajaxtoolkit:ToolkitScriptManager ID="SC1" runat="server" ScriptMode="Release" CombineScriptsHandlerUrl="~/CSScriptHandler.ashx" EnableScriptGlobalization="true" EnableScriptLocalization="true"> <Scripts> <asp:scriptreference assembly="AjaxControlToolkit" name="AjaxControlToolkit.Compat.Timer.Timer.js"/> <asp:scriptreference assembly="AjaxControlToolkit" name="AjaxControlToolkit.Common.Common.js"/> <asp:scriptreference assembly="AjaxControlToolkit" name="AjaxControlToolkit.Animation.Animations.js"/> <asp:scriptreference assembly="AjaxControlToolkit" name="AjaxControlToolkit.ExtenderBase.BaseScripts.js"/> <asp:scriptreference assembly="AjaxControlToolkit" name="AjaxControlToolkit.Animation.AnimationBehavior.js"/> </Scripts> </ajaxtoolkit:ToolkitScriptManager>

Mais malheureusement en faisant comme cela, tous les fichiers ajoutés manuellement seront ajoutés deux fois ! Une fois par le combinaison liée aux contrôles des toolkits et une fois manuellement, cela entraine bien sur de nombreuses erreurs. J'ai signalé le bug ici : ToolkitScriptManager add some script twice when added manually

Pour corriger ce problème il faut modifier le fichier ToolkitScriptManager.cs de la sorte puis recompiler :

/// <summary> /// ADDED : contains a cache with the partial name of an assembly and his full name /// </summary> private static Dictionary<String, String> _assemblyFullName = new Dictionary<string, string>(); /// <summary> /// OnResolveScriptReference override to track combinable scripts and update the script references /// </summary> /// <param name="e">event args</param> protected override void OnResolveScriptReference(ScriptReferenceEventArgs e) { base.OnResolveScriptReference(e); // If combining scripts and this is a candidate script if (_combineScripts && !String.IsNullOrEmpty(e.Script.Assembly) && !String.IsNullOrEmpty(e.Script.Name)) { // Initialize ScriptReference scriptReference = e.Script; // ADDED : get and set the fullname of the assembly if (!_assemblyFullName.ContainsKey(scriptReference.Assembly)) _assemblyFullName[scriptReference.Assembly] = Assembly.Load(scriptReference.Assembly).FullName; scriptReference.Assembly = _assemblyFullName[scriptReference.Assembly]; ScriptEntry scriptEntry = new ScriptEntry(scriptReference); if (IsScriptCombinable(scriptEntry)) { // ADDED : check if there is already a script with the same name and same assembly name if (!_scriptEntries.Exists(delegate(ScriptEntry entry) { if (!String.IsNullOrEmpty(scriptEntry.Assembly)) { return entry.Name == scriptEntry.Name && entry.Assembly == scriptEntry.Assembly; } else { return entry.Name == scriptEntry.Name; } })) { // Haven't seen this script yet; add it to the list and invalidate the Url _scriptEntries.Add(scriptEntry); _combinedScriptUrl = null; } } } }

Pour en savoir plus sur le ToolkitScriptManager :

PS : bizarre à chaque fois que j'utilise un truc des toolkits je tombe sur des bugs et je suis obligé de bidouiller ...

Posted: vendredi 14 septembre 2007 13:44 par cyril
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

dapoussin a dit :

Cool, merci pour ce post :)

J'ai rigoureusement suivi toutes les étapes mais mes pages contiennent toujours des liens JavaScript de ce genre : http://localhost/MyWebSite/ScriptResource.axd?d=Ma4urtJwtvwgHLWSkCThZT319JUAM4VJUj0vYs2elQsp-nIiHlVoK--r2zFPG8B6OERsdtBuoozLLYeVdftFCbXR0T8OBnMSIztkdJs_crA1&amp;t=633253790070461602

Pourtant mon site compile avec la nouvelle DLL du Toolkit et j'ai bien remplacé mon ScriptManager par un ToolkitScriptManager dans ma MasterPage. Est-ce que cela pourrait venir de l'utilisation d'un ScriptManagerProxy dans ma page ? Je l'utilise pour ajouter des références à des fichiers JS et des Web Services.

Quand j'analyse le poids des fichiers avec Firebug, j'ai l'impression qu'il n'y a aucun changement entre mon site avec ToolkitScriptManager et sans... aurais-tu une idée ?

Bye

Laurent

# septembre 14, 2007 16:21

cyril a dit :

Bonjour,

Je me suis peut etre mal exprimé : tous les fichier javascript ne seront pas compacté en 1 seul, en effet les proxy de WS, les fichiers que l'on ajoute directement via le path c'est à dire les fichiers qui ne sont pas contenu dans une ressource ainsi que les fichiers natif d'ASP.net ajax seront toujours téléchargés distinctement pour des raisons plus ou moins techniques :p

Mais normalement tu dois avoir un fichier avec un paramètre TSM_HiddenField. Bien sur il faut que tu utilises des controles toolkits pour que cela fonctionne (faut en fait que les scripts soient inclues en WebResource via un attribut qu'on trouve dans les toolkits)

# septembre 14, 2007 17:00

dapoussin a dit :

Bonjour Cyril,

Merci pour ta réponse (désolé pour le délai, je reviens de vacances :p), j'ai bien un TSM_HiddenField dans le HTML, mais sa value est vide. Il faudrait que je regarder en détail ce qui se passe avec ce champ.

Sinon, est-ce que ton hack du Toolkit est contenu dans la version 10920 sortie vendredi (j'ai la flemme de vérifier ^^). Ca serait pratique de revenir à la version officielle.

Bye

Laurent

# septembre 24, 2007 10:45

cyril a dit :

non ...

A croire que les gars des toolkits s'en fichent des corrections de bugs que je leur envoie ...

# septembre 24, 2007 11:03
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01

- SharePoint Online: Script PowerShell pour supprimer une colonne dans tous les sites d’une collection par Blog Technique de Romelard Fabrice le 11-27-2018, 18:01