2009-06-25 6 views
20

Wir haben eine ziemlich Standard E-Commerce-Szenario mit ausgelagerten Listen von Produkten innerhalb der Kategorien. Über oder über 80% der Besucher navigieren niemals über die erste Seite hinaus. Je nach Kategorie gibt es dann 5-10 weitere Seiten, die viel seltener aufgerufen werden. (Ja wir optimieren, was auf der ersten Seite angezeigt wird und eine gute Suche - aber das ist eine andere Diskussion)programmgesteuert steuern Ausgabe-Caching - deaktivieren oder aktivieren Sie den Cache nach Parameter Wert

Wir können nicht jede einzelne Seite der Ergebnisse zwischenspeichern, weil wir durch den Speicher beschränkt sind, aber den Vorteil des Caching nur die erste Seite der Ergebnisse für jede Kategorie wäre riesig.

Ich weiß, ich könnte etwas ähnliches mit Objekt-Caching tun, um die fraglichen Datasets zu speichern, aber ist dies möglich mit Ausgabe-Caching, vielleicht mit dem Objekt response.Cache?

Wo im Seitenlebenszyklus könnte dies getan werden? Vorrendern?

stark vereinfacht, ist die URL so etwas wie "/ Produktkategorie = etwas & Seite = 1?" Und ich würde wie die Logik etwas wollen (Pseudo-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. 

Wir ASP.NET verwenden 2.0, auf IIS 6/win2003.

+0

Werfen Sie einen Blick auf die letzte Antwort auf [diese] (http://stackoverflow.com/questions/1122837/how-do-i-configure-asp-net-outputcache-to-vary-by-http-vs -https) Beitrag. Ich hoffe das hilft. – James

Antwort

30

Statt die Outputcache-Direktive zu verwenden, können Sie die gleiche Sache programmatisch tun, wie folgt:

if (yourArbitraryCondition) { 
    OutputCacheParameters outputCacheSettings = new OutputCacheParameters(); 
    outputCacheSettings.Duration = 60; 
    InitOutputCache(outputCacheSettings); 
} 

Dadurch aus OnInit sollte gut funktionieren. Und natürlich können Sie das Caching-Verhalten optimieren, indem Sie die verschiedenen Eigenschaften des OutputCacheParameters festlegen, der dieselben Knöpfe wie die Direktive hat (genau das erzeugen wir, wenn Sie die Direktive benutzen).

Der entscheidende Punkt ist, dass Sie diese Logik nur bedingt ausführen, während die Direktive dies unbedingt vorschreibt.

UPDATE:

Als Alternative können Sie den niedrigen Level-Cache-API verwenden, die der Code oben auf gebaut wird. z.B.

Grundsätzlich ist es eine andere Möglichkeit, dasselbe zu tun, ohne APIs zu verwenden, die als "nicht aufgerufen werden" gekennzeichnet sind. Am Ende wird jeder Weg funktionieren, also wählen Sie.

+0

Werke. Jede Idee, warum 'InitOutputCache' ist' EditorBrowsableState.Never' und sollte nicht direkt nach http://msdn.microsoft.com/en-us/library/ms153473.aspx genannt werden? –

+1

Nun, es liegt hauptsächlich an einem Mangel an vorausschauendem Denken, als wir das zum ersten Mal entworfen haben. Auf der Seite gibt es eine Reihe von öffentlichen/geschützten APIs, die auf diese Weise gekennzeichnet sind. Sie sind alles Dinge, die durch generierten Code als Ergebnis der Verwendung verschiedener Syntax aufgerufen werden, und wir dachten, dass der Benutzer keine guten Gründe hatte, sie direkt aufzurufen. Aber die Wirklichkeit ist, dass es nichts Falsches daran ist, sie selbst zu nennen, und tatsächlich gibt es Zeiten wie hier, in denen man Dinge tun kann, die man mit der Seitensyntax nicht machen kann. Ich werde einen Fehler einreichen, um diese Flags zu entfernen, obwohl es zu spät für VS2010 ist. –

+0

Eine weitere Sache: Sie können tatsächlich das gleiche tun, indem Sie die Low-Level-Cache-API direkt aufrufen (und vermeiden InitOutputCache). Es wird gleich funktionieren, aber der Code wird komplexer. Lassen Sie mich wissen, wenn Sie diese alternative Lösung wünschen. –

0

Ich denke, Sie sollten in der Lage sein, die OutputCache directive mit der VaryByParam-Eigenschaft auf eine Semikolon getrennte Liste von Zeichenfolgen verwendet, um den Ausgabecache zu variieren.

Es sei denn, Sie wollten nur Cache nur wenn Seite == 1?

+0

das ist leider genau das, was ich will (nur wenn page == 1). Wenn ich jede Seite von Ergebnissen, die leicht sein würden, zwischenspeichern wollte, benutze varybyparam, wie du sagst. Sorry, ich glaube nicht, dass ich die Frage sehr klar formuliert, aber was ich nach nur subtely (aber signifikant) unterscheidet sich von der normalen Szenario jeder wird verwendet, um. –

5

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


Sie könnten

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

und implementieren sie in einer Weise, die einen festen Schlüssel für die erste Seite und einen zufälligen Schlüssel für alle anderen Seiten gibt verwenden. Sie können (und sollte) lassen Sie die scavenging Mechanismus kümmern sich um Speicher, aber Sie können HttpResponse.RemoveOutputCacheItem verwenden, um Cache-Elemente zu entfernen, wenn Sie müssen.

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); 
} 
1

Sie können immer noch die outputcache-Direktive verwenden, und meiner Meinung nach, lieber als Ihren Seitencode mit einer Reihe von Caching-Schrauben und Muttern zu werfen, gehen Sie besser mit einer wiederverwendbaren Lösung basierend auf der Handhabung in Global.asax die Art, wie Sie normalerweise ein VaryByCustom-Szenario verwenden würden.

Wenn Sie beispielsweise einen Paging-Ansatz mit einem Repeater verwenden, möchten Sie möglicherweise in Ihrem Suchszenario jedes Postback auf einer bestimmten Seite aus dem Cache ausschließen. Here ist ein Codebeispiel, das genau das tut. Der Ansatz erfordert lediglich das Httpcontext-Objekt mit Response.Cache.SetNoServerCaching zuzugreifen(), nach dem Einfangen unabhängig von Kriterien, für die Sie das Caching zu vermeiden. Ich hoffe das hilft.

Verwandte Themen