2010-06-09 10 views
7

stiamo cercando di ottenere il seguente lavoro scenario:accoda VersionNumber al asp: tag compositescript di ScriptManager

usiamo asp: ScriptManager/CompositeScripts di unire i nostri script in un paio di blocchi di script, ma dopo ogni distribuire al sistema di test che abbiamo avere problemi con i tester che non ottengono versioni aggiornate di css e javascript (cache del browser). Per il CSS abbiamo definito il nostro controllo utente css che aggiunge un parametro Siteversion "? V = 1.0.190" ad esempio al css url. Questa siteversion è definita in web.config/appsettings ed è urtata su ogni deploy.

Volevamo essere in grado di utilizzare la stessa strategia per i javascript, ma finora non ho avuto alcun successo. Durante il rendering del tag dello script. la ScriptManager rende

<script src="/ScriptResource.axd?d=..." type="text/javascript"></script> 

Dato che l'attuale siteversion configurato era 1.0.190, vorrei che per rendere

<script src="/ScriptResource.axd?d=...&v=1.0.190" type="text/javascript"></script> 

Come faccio ad avere al "script" output HTML da parte del direttore script in modo Posso cambiarlo? Non sembra essere presente nel roba reso in Render, RenderChildren o RenderControl

Distinti Andreas

+0

-1 Si apre una taglia e non hanno nemmeno scelto una risposta anche lì stanno lavorando! atteggiamento molto cattivo. – Aristos

risposta

3

Una soluzione molto più semplice in onload della tua pagina funziona bene per me:

ScriptManager.GetCurrent(this).CompositeScript.Path += "?v=" + MyBuildNumber.Value; 
+0

Tu, Signore, sei un genio – AndreasKnudsen

1

suggerirò un aproche spettacolo diverso. La chache è il tuo problema, quindi modifica l'intestazione della cache. Ecco un esempio che faccio e testarlo e funziona perfettamente. Sul global.asax sul proprio all'inizio della chiamata ...

protected void Application_BeginRequest(Object sender, EventArgs e) 
{ 
    HttpApplication app = (HttpApplication)sender; 

    string cTheFile = HttpContext.Current.Request.Path; 

    if (cTheFile.EndsWith("ScriptResource.axd", StringComparison.InvariantCultureIgnoreCase)) 
    { 
     // here is the trick with your version ! 
     string etag = "\"" + app.Context.Request.QueryString.ToString().GetHashCode().ToString() + "1.0.190" + "\""; 
     string incomingEtag = app.Request.Headers["If-None-Match"]; 

     app.Response.Cache.SetETag(etag); 

     if (String.Compare(incomingEtag, etag) == 0) 
     { 
      app.Response.StatusCode = (int)System.Net.HttpStatusCode.NotModified; 
      app.Response.StatusDescription = "Not Modified";        
     } 
     else 
     { 
      app.Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(1)); 
      app.Response.Cache.SetMaxAge(new TimeSpan(0, 1, 0)); 
      app.Response.Cache.SetCacheability(HttpCacheability.Public); 
     } 
    } 
} 
+1

Il problema con questo approccio è che il browser finirà per effettuare molti round trip non necessari al server web solo per scoprire che il file non è stato modificato dall'ultima volta. Su un sito Web non banale, ciò può avere un impatto significativo sulle prestazioni del sito (round trip = bad). Il vantaggio di utilizzare l'url versione è che è possibile memorizzare gli script in modo molto aggressivo e forzare il browser a compiere un round trip quando lo script è stato aggiornato (aumentando il numero di versione). – Andy

4

Ho scavato intorno nel riflettore per un po 'e sembra che questo è, purtroppo, una cosa difficile da aggiungere. La SM non ha fornito punti di estensione validi che potessi trovare. Tuttavia, se siete disposti a ricorrere a un bel trucco riflessione, aggiungendo la seguente ControlAdapter per ScriptManager dovrebbe fare il trucco:

public class VersionedScriptManagerAdapter : ControlAdapter 
{ 
    protected new ScriptManager Control 
    { 
     get { return (ScriptManager) base.Control; } 
    } 

    protected override void OnPreRender(System.EventArgs e) 
    { 
     base.OnPreRender(e); 

     var compositeScriptField = Control.GetType().GetField("_compositeScript", 
                   BindingFlags.NonPublic | BindingFlags.Instance); 
     var currentCompositeScript = Control.CompositeScript; 
     var versionedCompositeScript = new VersionedCompositeScriptReference(); 
     CopyCompositeScript(currentCompositeScript, versionedCompositeScript); 
     compositeScriptField.SetValue(Control, versionedCompositeScript); 
    } 

    private void CopyCompositeScript(CompositeScriptReference sourceCompositeScript, CompositeScriptReference targetCompositeScript) 
    { 
     targetCompositeScript.Path = sourceCompositeScript.Path; 
     targetCompositeScript.ResourceUICultures = sourceCompositeScript.ResourceUICultures; 
     targetCompositeScript.ScriptMode = sourceCompositeScript.ScriptMode; 
     foreach (var scriptReference in sourceCompositeScript.Scripts) 
     { 
      targetCompositeScript.Scripts.Add(scriptReference); 
     } 
    } 

    private class VersionedCompositeScriptReference : CompositeScriptReference 
    { 
     protected override string GetUrl(ScriptManager scriptManager, bool zip) 
     { 
      string version = ConfigurationManager.AppSettings["ScriptVersion"]; 
      return base.GetUrl(scriptManager, zip) + "&v=" + version; 
     } 
    } 
} 

Poi, per il collegamento di questo adattatore di controllo, è necessario creare un Web.browser file e inserirlo nella cartella App_Browsers sul sito Web. Il file Web.browser dovrebbe assomigliare a questo:

<browsers> 
    <browser refID="Default"> 
     <controlAdapters> 
     <adapter controlType="System.Web.UI.ScriptManager" 
      adapterType="MyNamespace.VersionedScriptManagerAdapter"> 
     </adapter> 
     </controlAdapters> 
    </browser> 
</browsers> 

Ho provato questo e ha funzionato per me. Spero sia utile per te.

+0

+1 Andy voto la tua risposta perché è più vicina alla domanda, e perché è meglio che qualcuno ottenga la taglia se andreas dimentica di selezionarne una. – Aristos

+0

In qualche modo il mio snippet Web.browser non è stato inserito nel mio post originale.Ecco che cosa sarebbe simile: \t \t \t \t \t \t \t \t \t Andy

+0

questo codice, infine, non il suo lavoro! Penso che abbia bisogno di più lavoro e prove. – Aristos

Problemi correlati