Pytanie w sprawie outputcache, asp.net, iis-6 – programowo steruj buforowaniem wyjścia - wyłącz lub włącz pamięć podręczną zgodnie z wartością parametru

20

Mamy dość standardowy scenariusz e-commerce z listami stronicowanych produktów w kategoriach. Na lepsze lub gorsze, około 80% odwiedzających nigdy nie przechodzi przez pierwszą stronę, w zależności od kategorii może być 5-10 dodatkowych stron wyników, które są wyświetlane znacznie rzadziej. (Tak, optymalizujemy to, co pojawia się na pierwszej stronie i mamy dobre wyszukiwanie - ale to inna dyskusja)

Nie możemy buforować każdej pojedynczej strony wyników, ponieważ jesteśmy ograniczeni pamięcią, ale korzyści z buforowania tylko pierwszej strony wyników dla każdej kategorii byłyby ogromne.

Wiem, że mógłbym zrobić coś podobnego przy użyciu buforowania obiektów do przechowywania danych zestawów danych, ale czy jest to możliwe przy użyciu buforowania danych wyjściowych, być może przy użyciu obiektu response.Cache?

Gdzie w cyklu życia strony można to zrobić? Czy renderujesz wcześniej?

Znacznie uproszczony, adres URL jest podobny do „/ ProductList? Category = coś & Page = 1”, a ja chciałbym logiki coś takiego (pseudokod):

<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>

Korzystamy z ASP.NET 2.0 na IIS 6 / win2003.

Spójrz na ostatnią odpowiedź nato słupek. Mam nadzieję, że to pomoże. James

Twoja odpowiedź

5   odpowiedzi
0

Dyrektywa OutputCache z właściwością VaryByParam ustawioną na rozdzieloną średnikami listę ciągów używanych do zmiany wyjściowej pamięci podręcznej.

Chyba że chciałeś po prostu buforowaćtylko kiedy strona == 1?

niestety to jest dokładnie to, czego chcę (Tylko gdy strona == 1). Jeśli chciałbym cache'ować każdą stronę wyników, która byłaby łatwa, za pomocą varybyparam, jak mówisz. Przepraszam, nie sądzę, że sformułowałem to pytanie bardzo wyraźnie, ale to, czego szukam, jest tylko nieznacznie (ale znacząco) inne niż normalny scenariusz, do którego wszyscy są przyzwyczajeni. Andrew M
4

HttpCachePolicy.AddValidationCallback

Widziećhttp://www.hanselman.com/blog/AdvancedASPNETCachingAndAddValidationCallBack.aspx - Jest pełny przykład, który dokładnie odpowiada na to pytanie.

5

edytować: Podoba mi się odpowiedź Davida Ebbo znacznie lepiej niż moja.

Możesz użyć

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

i zaimplementuj go w sposób, który zwraca stały klucz dla pierwszej strony i losowy klucz dla wszystkich innych stron. Możesz (ipowinien) niechoczyszczanie mechanizm dba o pamięć, ale możesz użyćHttpResponse.RemoveOutputCacheItem aby usunąć elementy pamięci podręcznej, jeśli musisz.

<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>
31

możesz zrobić to samo programowo, w następujący sposób:

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

Wykonanie tego z OnInit powinno działać dobrze. Oczywiście możesz dostosować zachowanie buforowania, ustawiając różne właściwości w OutputCacheParameter, który ma wszystkie takie same pokrętła jak dyrektywa (w rzeczywistości to właśnie generujemy podczas korzystania z dyrektywy).

Kluczową kwestią jest to, że logikę tę wykonujesz tylko warunkowo, podczas gdy dyrektywa czyni ją bezwarunkową.

AKTUALIZACJA:

Alternatywnie można użyć interfejsu API pamięci podręcznej niskiego poziomu, na którym jest zbudowany powyższy kod. na przykład

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

Zasadniczo jest to inny sposób robienia tego samego, bez użycia jakiegokolwiek API oznaczonego jako „nie powinno się nazywać”. W końcu każda z nich zadziała, więc wybierz swoją.

najwyższy kod rzuca wyjątek, jeśli nie dołączasz outputCacheSettings.VaryByParam = "none"; NSjonas
Czy może to działać z buforowaniem fragmentów w celu buforowania poszczególnych kontrolek generowanych dynamicznie? Innymi słowy, co jeśli jedna kontrola dynamiczna zmienia się o jeden parametr, inna zmienia się o inny parametr? sagescrub
Jeszcze jedno: możesz zrobić to samo, wywołując bezpośrednio interfejs API pamięci podręcznej niskiego poziomu (i uniknąć InitOutputCache). Będzie działać tak samo, ale kod będzie bardziej złożony. Daj mi znać, jeśli chcesz to alternatywne rozwiązanie. David Ebbo
Cóż, to głównie z powodu braku perspektywicznego myślenia, kiedy po raz pierwszy to zaprojektowaliśmy. Na stronie istnieje wiele publicznych / chronionych interfejsów API, które są oznaczone w ten sposób. Są to wszystkie rzeczy, które są wywoływane przez wygenerowany kod w wyniku użycia różnych składni, i doszliśmy do wniosku, że użytkownik nie miał żadnych dobrych powodów, aby wywoływać je bezpośrednio. Ale rzeczywistość jest taka, że ​​nie ma nic złego w wywoływaniu ich samodzielnie, a tak naprawdę są takie momenty, w których pozwala ci robić rzeczy, których nie możesz zrobić ze składnią strony. Zgłoszę błąd, aby usunąć te flagi, ale VS2010 jest za późno. David Ebbo
Prace. Jakiś pomysł dlaczegoInitOutputCache jestEditorBrowsableState.Never i nie powinny być wywoływane bezpośrednio zgodnie zmsdn.microsoft.com/en-us/library/ms153473.aspx? Josef Pfleger
1

a moim zdaniem, zamiast zaśmiecać kod strony za pomocą paczki z pamięcią podręczną, lepiej pójść z rozwiązaniem wielokrotnego użytku, opierając się na obsłudze w Global.asax tak, jak zwykle czy byłby scenariusz VaryByCustom.

Na przykład, jeśli używasz podejścia przywoławczego z repeaterem, możesz po prostu w swoim scenariuszu wyszukiwania wykluczyć z pamięci podręcznej wszelkie informacje zwrotne na określonej stronie.Tutaj to przykład kodu, który właśnie to robi. Podejście to wymaga jedynie użycia obiektu HttpContext w celu uzyskania dostępu do Response.Cache.SetNoServerCaching (), po przechwyceniu wszystkich kryteriów, dla których chcesz uniknąć buforowania. Mam nadzieję, że to pomoże.

Powiązane pytania