Frage an outputcache, asp.net, iis-6 – Ausgabecache programmgesteuert steuern - Cache je nach Parameterwert deaktivieren oder aktivieren

20

Wir haben ein ziemlich normales E-Commerce-Szenario mit seitenweisen Produktlisten innerhalb von Kategorien. Gut oder schlecht, 80% der Besucher navigieren nie über die erste Seite hinaus. Je nach Kategorie können dann 5-10 weitere Ergebnisseiten vorhanden sein, die weitaus seltener angezeigt werden. (Ja, wir optimieren das, was auf der ersten Seite angezeigt wird, und haben eine gute Suche - aber das ist eine andere Diskussion.)

Wir können nicht jede einzelne Ergebnisseite zwischenspeichern, da der Arbeitsspeicher dies zulässt. Der Vorteil des Zwischenspeicherns nur der ersten Ergebnisseite für jede Kategorie wäre jedoch immens.

Ich weiß, dass ich mit der Objektzwischenspeicherung etwas Ähnliches tun könnte, um die fraglichen Datasets zu speichern. Ist dies jedoch mit der Ausgabezwischenspeicherung möglich, möglicherweise mithilfe des response.Cache-Objekts?

Wo im Lebenszyklus der Seite könnte dies geschehen? Vorrendern?

Die URL ist stark vereinfacht: "/ ProductList? Category = something & Page = 1" Und ich möchte eine Logik wie (Pseudocode):

<code>If paramater "Page" equals 1
   Use output caching: vary by param = "categoryName; page"
else
   Don't use caching at all, just render the page from scratch.
</code>

Wir verwenden ASP.NET 2.0 unter IIS 6 / win2003.

Schauen Sie sich die letzte Antwort andiese Post. Ich hoffe das hilft. James

Deine Antwort

5   die antwort
31

Anstatt die OutputCache-Direktive zu verwenden, können Sie das gleiche programmgesteuert tun:

<code>if (yourArbitraryCondition) {
  OutputCacheParameters outputCacheSettings = new OutputCacheParameters();
  outputCacheSettings.Duration = 60;
  InitOutputCache(outputCacheSettings);
}
</code>

Dies von OnInit aus zu tun, sollte gut funktionieren. Und natürlich können Sie das Caching-Verhalten optimieren, indem Sie die verschiedenen Eigenschaften für OutputCacheParameter festlegen, die alle die gleichen Regler wie die Direktive haben (das ist es, was wir generieren, wenn Sie die Direktive verwenden).

Der entscheidende Punkt ist, dass Sie diese Logik nur bedingt ausführen, während die Direktive sie bedingungslos macht.

AKTUALISIEREN:

Alternativ können Sie die Cache-API auf niedriger Ebene verwenden, auf der der obige Code basiert. z.B.

<code>HttpCachePolicy cache = Response.Cache;
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(Context.Timestamp.AddSeconds(60));
cache.VaryByParams["categoryName"] = true;
</code>

Im Grunde ist es eine andere Möglichkeit, das Gleiche zu tun, ohne APIs zu verwenden, die als "sollte nicht aufgerufen werden" gekennzeichnet sind. Am Ende wird jeder Weg funktionieren, also treffen Sie Ihre Wahl.

Der oberste Code löst eine Ausnahme aus, wenn Sie outputCacheSettings.VaryByParam = "none" nicht einschließen. NSjonas
Funktioniert dies mit der Fragment-Zwischenspeicherung zum Zwischenspeichern einzelner Steuerelemente, die dynamisch generiert werden? Mit anderen Worten, was ist, wenn eine dynamische Steuerung von einem Parameter zum anderen variiert? sagescrub
Nun, es liegt hauptsächlich an einem Mangel an vorausschauendem Denken, als wir dies zum ersten Mal entworfen haben. Es gibt eine Reihe von öffentlichen / geschützten APIs auf der Seite, die auf diese Weise gekennzeichnet sind. Dies sind alles Dinge, die vom generierten Code als Ergebnis der Verwendung verschiedener Syntax aufgerufen werden, und wir stellten fest, dass der Benutzer keine guten Gründe hatte, sie direkt aufzurufen. Die Realität ist jedoch, dass es nichts Falsches gibt, wenn Sie sie selbst aufrufen. In der Tat gibt es Zeiten wie hier, in denen Sie Dinge tun können, die Sie mit der Seitensyntax nicht tun konnten. Ich werde einen Fehler melden, um diese Flags zu entfernen, obwohl es für VS2010 viel zu spät ist. David Ebbo
Funktioniert. Irgendeine Idee warumInitOutputCache istEditorBrowsableState.Never und sollte nicht direkt laut gerufen werdenmsdn.microsoft.com/en-us/library/ms153473.aspx? Josef Pfleger
Eine weitere Sache: Sie können dasselbe tun, indem Sie die Low-Level-Cache-API direkt aufrufen (und InitOutputCache vermeiden). Es wird genauso funktionieren, aber der Code wird komplexer sein. Lassen Sie mich wissen, ob Sie diese alternative Lösung wünschen. David Ebbo
5

bearbeiten: Ich mag die Antwort von David Ebbo viel besser als meine eigene.

Du könntest benutzen

<code><%@ OutputCache Duration="60"  VaryByParam="none" VaryByCustom="pageOne" %>
</code>

und implementieren Sie es so, dass ein fester Schlüssel für die erste Seite und ein zufälliger Schlüssel für alle anderen Seiten zurückgegeben wird. Sie können (undsollte) lassen Sie dieSpülen Mechanismus kümmern sich um Speicher, aber Sie können verwendenHttpResponse.RemoveOutputCacheItem um Cache-Elemente zu entfernen, wenn Sie müssen.

<code>public override string GetVaryByCustomString(HttpContext ctx, string custom)
{
    if(custom == "pageOne")
    {
        if(ctx.Request["page"] == "1")
        {
            return "1";
        }

        HttpResponse.RemoveOutputCacheItem("/Default.aspx");
        return Guid.NewGuid().ToString();
    }
    return base.GetVaryByCustomString(ctx, custom);
}
</code>
0

Ich denke du solltest das benutzen könnenOutputCache-Direktive mit der Eigenschaft VaryByParam, die auf eine durch Semikolon getrennte Liste von Zeichenfolgen festgelegt ist, die zum Variieren des Ausgabecaches verwendet werden.

Es sei denn, Sie wollten nur Cachenur wann Seite == 1?

leider ist das genau das was ich will (nur wenn seite == 1). Wenn ich jede Seite mit Ergebnissen zwischenspeichern möchte, wäre das einfach, wenn Sie, wie Sie sagen, varybyparam verwenden. Es tut mir leid, ich glaube nicht, dass ich die Frage sehr klar formuliert habe, aber das, wonach ich suche, unterscheidet sich nur geringfügig (aber signifikant) von dem normalen Szenario, an das jeder gewöhnt ist. Andrew M
4

Ich glaube, der beste Weg, dies zu tun, ist zu verwendenHttpCachePolicy.AddValidationCallback

Sehenhttp://www.hanselman.com/blog/AdvancedASPNETCachingAndAddValidationCallBack.aspx - Es gibt ein vollständiges Beispiel, das genau diese Frage beantwortet.

1

Sie können weiterhin die Direktive outputcache verwenden, und meiner Meinung nach ist es besser, eine wiederverwendbare Lösung zu wählen, die darauf basiert, dass Sie dies in Global.asax wie gewohnt handhaben, anstatt Ihren Seitencode mit ein paar Schrauben und Muttern zu verunreinigen würde jedes VaryByCustom-Szenario.

Wenn Sie beispielsweise einen Paging-Ansatz mit einem Repeater verwenden, möchten Sie in Ihrem Suchszenario möglicherweise einfach ein Postback auf einer bestimmten Seite aus dem Cache ausschließen.Hier ist ein Codebeispiel, das genau das tut. Der Ansatz erfordert lediglich die Verwendung des HttpContext-Objekts, um auf Response.Cache.SetNoServerCaching () zuzugreifen, nachdem alle Kriterien abgefangen wurden, für die Sie das Zwischenspeichern vermeiden möchten. Ich hoffe das hilft.

Verwandte Fragen