Pergunta sobre iis-6, outputcache, asp.net – controlar programaticamente o cache de saída - desative ou ative o cache de acordo com o valor do parâmetro

20

Temos um cenário de comércio eletrônico bastante padronizado com listas paginadas de produtos nas categorias. Para melhor ou pior, cerca de 80% dos visitantes nunca navegam além da primeira página, dependendo da categoria, pode haver de 5 a 10 páginas a mais de resultados que são visualizados com muito menos frequência. (Sim, otimizamos o que aparece na primeira página e temos boa pesquisa - mas essa é uma discussão diferente)

Não podemos armazenar em cache cada página de resultados, porque somos limitados pela memória, mas o benefício de armazenar em cache apenas a primeira página de resultados para cada categoria seria enorme.

Eu sei que eu poderia fazer algo semelhante usando o cache de objetos para armazenar os conjuntos de dados em questão, mas isso é possível usando o cache de saída, talvez usando o objeto response.Cache?

Onde no ciclo de vida da página isso poderia ser feito? Pré-renderizar?

Muito simplificada, a URL é algo como "/ ProductList? Category = something & Page = 1" E eu quero lógica algo como (pseudocódigo):

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

Estamos usando o ASP.NET 2.0, no IIS 6 / win2003.

Dê uma olhada na última resposta emisto postar. Eu espero que isso ajude. James

Sua resposta

5   a resposta
5

editar: Eu gosto da resposta de David Ebbo muito melhor que a minha.

Você poderia usar

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

e implementá-lo de uma maneira que retorne uma chave fixa para a primeira página e uma chave aleatória para todas as outras páginas. Você pode (edevemos) Deixe olimpeza mecanismo de cuidar da memória, mas você pode usarHttpResponse.RemoveOutputCacheItem para remover itens de cache se você precisar.

<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

Diretiva de OutputCache com a propriedade VaryByParam definida como uma lista de cadeias separadas por ponto e vírgula usada para variar o cache de saída.

A menos que você estivesse querendo apenas cache quando página == 1?

infelizmente isso é exatamente o que eu quero (somente quando a página == 1). Se eu quisesse armazenar em cache todas as páginas de resultados que seriam fáceis, usando o varybyparam como você diz. Desculpe, eu não acho que eu tenha formulado a pergunta com muita clareza, mas o que eu estou procurando é apenas subtis (mas significativamente) diferente do cenário normal que todos estão acostumados. Andrew M
4
1

e em minha opinião, ao invés de lixo seu código de página com um monte de porcas e parafusos de armazenamento em cache, é melhor ir com uma solução reutilizável baseada em lidar com isso no Global.asax da maneira que você normalmente qualquer cenário VaryByCustom.

Portanto, por exemplo, se você estiver usando uma abordagem de paginação com um repetidor, poderá simplesmente, em seu cenário de pesquisa, desejar excluir qualquer postagem de uma determinada página do cache.Aqui é um exemplo de código que faz exatamente isso. A abordagem requer apenas o uso do objeto HttpContext para acessar Response.Cache.SetNoServerCaching (), após capturar qualquer critério para o qual você deseja evitar o armazenamento em cache. Eu espero que isso ajude.

31

você pode fazer a mesma coisa programaticamente, da seguinte maneira:

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

Fazer isso de OnInit deve funcionar bem. E, obviamente, você pode ajustar o comportamento do cache definindo as várias propriedades no OutputCacheParameter, que tem todos os mesmos botões da diretiva (na verdade, é isso que geramos quando você usa a diretiva).

O ponto chave é que você está apenas executando essa lógica condicionalmente, enquanto a diretiva a torna incondicional.

ATUALIZAR:

Como alternativa, você pode usar a API de cache de baixo nível na qual o código acima está construído. por exemplo.

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

Basicamente, é outra maneira de fazer a mesma coisa, sem usar qualquer API marcada como 'não deveria ser chamada'. No final, de qualquer forma vai funcionar, então faça a sua escolha.

Bem, é principalmente devido a alguma falta de pensamento quando projetamos isso. Há várias APIs públicas / protegidas na página marcadas dessa maneira. São todas as coisas que são chamadas pelo código gerado como resultado da utilização de várias sintaxes, e achamos que o usuário não tinha boas razões para chamá-las diretamente. Mas a realidade é que não há nada de errado em chamá-los e, na verdade, há momentos como aqui em que ele permite que você faça coisas que você não poderia fazer com a sintaxe da página. Vou arquivar um bug para remover esses sinalizadores, embora seja tarde demais para o VS2010. David Ebbo
o código superior lança e exceção se você não incluir outputCacheSettings.VaryByParam = "none"; NSjonas
Trabalho. Qualquer ideia porqueInitOutputCache éEditorBrowsableState.Never e não deve ser chamado diretamente de acordo commsdn.microsoft.com/pt-br/library/ms153473.aspx? Josef Pfleger
Isso pode funcionar com o armazenamento em cache de fragmentos para o armazenamento em cache de controles individuais que são gerados dinamicamente? Em outras palavras, e se um controle dinâmico varia por um parâmetro, outro varia por outro parâmetro? sagescrub
Só mais uma coisa: você pode realmente fazer a mesma coisa chamando a API de cache de baixo nível diretamente (e evitar InitOutputCache). Funcionará da mesma forma, mas o código será mais complexo. Deixe-me saber se você quer essa solução alternativa. David Ebbo

Perguntas relacionadas