... oder wie ich gelernt habe, mich nicht mehr zu sorgen und einfach Code gegen vollständig undokumentierte APIs von Microsoft zu schreiben . Gibt es eine tatsächliche Dokumentation der offiziellen System.Web.Optimization
Veröffentlichung? Weil ich sicher keine finden kann, es keine XML-Dokumente gibt und alle Blog-Beiträge auf die RC-API verweisen, die sich wesentlich unterscheidet. Wie auch immer ..
Ich schreibe Code, um Javascript-Abhängigkeiten automatisch aufzulösen, und erstelle aus diesen Abhängigkeiten im laufenden Betrieb Bundles. Alles funktioniert hervorragend, außer wenn Sie Skripte bearbeiten oder auf andere Weise Änderungen vornehmen, die sich auf ein Bundle auswirken würden, ohne die Anwendung neu zu starten, werden die Änderungen nicht übernommen. Daher habe ich eine Option hinzugefügt, um das Caching der Abhängigkeiten für die Verwendung in der Entwicklung zu deaktivieren.
Anscheinend wird BundleTables
die URL jedoch auch dann zwischengespeichert , wenn sich die Bundle-Sammlung geändert hat . Wenn ich beispielsweise in meinem eigenen Code ein Bundle neu erstellen möchte, gehe ich folgendermaßen vor:
// remove an existing bundle
BundleTable.Bundles.Remove(BundleTable.Bundles.GetBundleFor(bundleAlias));
// recreate it.
var bundle = new ScriptBundle(bundleAlias);
// dependencies is a collection of objects representing scripts,
// this creates a new bundle from that list.
foreach (var item in dependencies)
{
bundle.Include(item.Path);
}
// add the new bundle to the collection
BundleTable.Bundles.Add(bundle);
// bundleAlias is the same alias used previously to create the bundle,
// like "~/mybundle1"
var bundleUrl = BundleTable.Bundles.ResolveBundleUrl(bundleAlias);
// returns something like "/mybundle1?v=hzBkDmqVAC8R_Nme4OYZ5qoq5fLBIhAGguKa28lYLfQ1"
Immer wenn ich ein Bundle mit demselben Alias entferne und neu erstelle , passiert absolut nichts: Die bundleUrl
Rückgabe von ResolveBundleUrl
ist dieselbe wie vor dem Entfernen und Neuerstellen des Bundles. Mit "dasselbe" meine ich, dass der Inhalts-Hash unverändert bleibt, um den neuen Inhalt des Bundles widerzuspiegeln.
bearbeiten ... eigentlich ist es viel schlimmer als das. Das Bundle selbst wird irgendwie außerhalb der Bundles
Sammlung zwischengespeichert. Wenn ich nur meinen eigenen zufälligen Hash generiere, um zu verhindern, dass der Browser das Skript zwischenspeichert, gibt ASP.NET das alte Skript zurück . Offensichtlich BundleTable.Bundles
bewirkt das Entfernen eines Bundles aus nichts.
Ich kann einfach den Alias ändern, um dieses Problem zu umgehen, und das ist für die Entwicklung in Ordnung, aber ich mag diese Idee nicht, da ich entweder nach jedem Laden der Seite Aliase verwerfen muss oder eine BundleCollection habe, deren Größe zunimmt jede Seite wird geladen. Wenn Sie dies in einer Produktionsumgebung aktiviert lassen, wäre dies eine Katastrophe.
Es scheint also, dass ein Skript, wenn es bereitgestellt wird, unabhängig vom tatsächlichen BundleTables.Bundles
Objekt zwischengespeichert wird. Wenn Sie also eine URL wiederverwenden, selbst wenn Sie das Bundle, auf das sie verwiesen hat, vor der Wiederverwendung entfernt haben, antwortet sie mit dem, was sich in ihrem Cache befindet, und das Ändern des Bundles
Objekts leert den Cache nicht - also nur neue Elemente (oder Vielmehr würden jemals neue Gegenstände mit einem anderen Namen verwendet.
Das Verhalten scheint seltsam ... Wenn Sie etwas aus der Sammlung entfernen, sollte es aus dem Cache entfernt werden. Aber das tut es nicht. Es muss eine Möglichkeit geben, diesen Cache zu leeren und den aktuellen Inhalt des Caches BundleCollection
anstelle dessen zu verwenden, was beim ersten Zugriff auf dieses Bundle zwischengespeichert wurde.
Irgendeine Idee, wie ich das machen würde?
Es gibt diese ResetAll
Methode, die einen unbekannten Zweck hat, aber trotzdem die Dinge kaputt macht, so dass es nicht so ist.
quelle
Antworten:
Wir hören, dass Sie Probleme mit der Dokumentation haben. Leider ändert sich diese Funktion immer noch recht schnell, und das Generieren von Dokumentation hat einige Verzögerungen und kann fast sofort veraltet sein. Ricks Blog-Post ist aktuell und ich habe versucht, auch hier Fragen zu beantworten, um in der Zwischenzeit aktuelle Informationen zu verbreiten. Wir sind derzeit dabei, unsere offizielle Codeplex-Site einzurichten, die immer über die aktuelle Dokumentation verfügt.
Nun zu Ihrer speziellen Frage, wie Bundles aus dem Cache geleert werden sollen.
Wir speichern die gebündelte Antwort im ASP.NET-Cache unter Verwendung eines Schlüssels, der aus der angeforderten Bundle-URL generiert wurde, dh
Context.Cache["System.Web.Optimization.Bundle:~/bundles/jquery"]
wir richten auch Cache-Abhängigkeiten für alle Dateien und Verzeichnisse ein, die zum Generieren dieses Bundles verwendet wurden. Wenn sich also eine der zugrunde liegenden Dateien oder Verzeichnisse ändert, wird der Cache-Eintrag gelöscht.Wir unterstützen die Live-Aktualisierung der BundleTable / BundleCollection auf Anfrage nicht wirklich. Das vollständig unterstützte Szenario besteht darin, dass Bundles während des App-Starts konfiguriert werden (dies bedeutet, dass im Webfarm-Szenario alles ordnungsgemäß funktioniert, andernfalls würden einige Bundle-Anforderungen 404 sein, wenn sie an den falschen Server gesendet werden). Wenn Sie sich Ihr Codebeispiel ansehen, ist meine Vermutung, dass Sie versuchen, die Bundle-Sammlung bei einer bestimmten Anforderung dynamisch zu ändern? Jede Art von Bundle-Administration / Rekonfiguration sollte von einem Zurücksetzen der App-Domäne begleitet werden, um sicherzustellen, dass alles korrekt eingerichtet wurde.
Vermeiden Sie es daher, Ihre Bundle-Definitionen zu ändern, ohne Ihre App-Domain zu recyceln. Es steht Ihnen frei, die tatsächlichen Dateien in Ihren Bundles zu ändern, die automatisch erkannt werden sollen, und neue Hashcodes für Ihre Bundle-URLs zu generieren.
quelle
Ich habe ein ähnliches Problem.
In meiner Klasse habe
BundleConfig
ich versucht zu sehen, wie sich die Verwendung auswirktBundleTable.EnableOptimizations = true
.Alles hat gut funktioniert.
Irgendwann habe ich ein Debugging durchgeführt und die Eigenschaft auf false gesetzt.
Ich hatte Mühe zu verstehen, was geschah, weil es den Anschein hatte, als würde das Bundle für jquery (das erste) nicht aufgelöst und geladen (
/bundles/jquery?v=
).Nach einigem Fluchen denke ich (?!) Habe ich es geschafft, die Dinge zu klären. Versuchen Sie hinzuzufügen
bundles.Clear()
undbundles.ResetAll()
zu Beginn der Registrierung sollten die Dinge wieder funktionieren.Ich habe festgestellt, dass ich diese beiden Methoden nur ausführen muss, wenn ich die
EnableOptimizations
Eigenschaft ändere .AKTUALISIEREN:
Wenn ich tiefer grabe, habe ich das herausgefunden
BundleTable.Bundles.ResolveBundleUrl
und habe@Scripts.Url
anscheinend Probleme, den Bundle-Pfad zu lösen.Der Einfachheit halber habe ich einige Bilder hinzugefügt:
Ich habe die Optimierung deaktiviert und einige Skripte gebündelt.
Das gleiche Bündel ist im Körper enthalten.
@Scripts.Url
gibt mir den "optimierten" Pfad des Bündels, während@Scripts.Render
der richtige generiert wird.Das gleiche passiert mit
BundleTable.Bundles.ResolveBundleUrl
.Ich verwende Visual Studio 2010 + MVC 4 + Framework .Net 4.0.
quelle
ResetAll
und habe versuchtEnableOptimizations
, sowohl beim Start als auch inline auf false zu setzen, wenn ich den Cache zurücksetzen muss. Es passiert nichts. Argh.In Anbetracht der Empfehlungen von Hao Kung, dies aufgrund von Webfarmszenarien nicht zu tun, gibt es meines Erachtens viele Szenarien, in denen Sie dies möglicherweise tun möchten. Hier ist eine Lösung:
Sie können den obigen Code jederzeit aufrufen und Ihre Bundles werden aktualisiert. Dies funktioniert sowohl, wenn EnableOptimizations wahr oder falsch ist - mit anderen Worten, dies wirft das richtige Markup in Debug- oder Live-Szenarien aus, mit:
quelle
GenerateBundleResponse
Ich hatte auch Probleme beim Aktualisieren von Bundles ohne Neuerstellung. Hier sind die wichtigen Dinge zu verstehen:
Wenn Sie also wissen, dass Sie beim dynamischen Bündeln Code schreiben können, damit der virtuelle Pfad des Bundles auf den Dateipfaden basiert. Ich empfehle, die Dateipfade zu hashen und diesen Hash an das Ende des virtuellen Pfads des Bundles anzuhängen. Auf diese Weise werden der virtuelle Pfad und das Bundle aktualisiert, wenn sich die Dateipfade ändern.
Hier ist der Code, mit dem ich das Problem gelöst habe:
quelle
Aggregate
Verkettung von Zeichenfolgen generell zu vermeiden , da das Risiko besteht, dass jemand bei wiederholter Verwendung nicht an den inhärenten Algorithmus von Schlemiel the Painter denkt+
. Stattdessen einfach tunstring.Join("", filePaths)
. Dies wird dieses Problem auch bei sehr großen Eingängen nicht haben.Haben Sie versucht, von ( StyleBundle oder ScriptBundle ) abzuleiten , Ihrem Konstruktor keine Einschlüsse hinzuzufügen und dann zu überschreiben ?
Ich mache das für dynamische Stylesheets und EnumerateFiles wird bei jeder Anfrage aufgerufen. Es ist wahrscheinlich nicht die beste Lösung, aber es funktioniert.
quelle
Ich entschuldige mich für die Wiederbelebung eines toten Threads. Bei einer Umbraco-Site stieß ich jedoch auf ein ähnliches Problem mit dem Bundle-Caching, bei dem die Stylesheets / Skripte automatisch minimiert werden sollten, wenn der Benutzer die hübsche Version im Backend änderte.
Der Code, den ich bereits hatte, war (in der onSaved-Methode für das Stylesheet):
und (onApplicationStarted):
Egal was ich versuchte, die Datei "~ / bundles / styles.min.css" schien sich nicht zu ändern. Im Kopf meiner Seite habe ich ursprünglich wie folgt in das Stylesheet geladen:
Ich habe es jedoch zum Laufen gebracht, indem ich dies geändert habe in:
Die Styles.Render-Methode zieht eine Abfragezeichenfolge am Ende des Dateinamens ein, von der ich vermute, dass es sich um den von Hao oben beschriebenen Cache-Schlüssel handelt.
Für mich war es so einfach. Hoffe das hilft allen anderen wie mir, die dies stundenlang gegoogelt haben und nur einige Jahre alte Beiträge finden konnten!
quelle