Por Dennes Torres dennes@bufaloinfo.com.brDennes Torres possui as certificações MCAD, MCSD,MCSE, MCDBA e MCT. Atualmente atua como diretor da Búfalo Informática, líder do grupo de usuários DevASPNet, co-lider dos grupos devSQL e getWindows no Rio de Janeiro, podendo sempre ser encontrado na lista de discussão do grupo DevASPNet (devaspnet-subscribe@yahoogrupos.com.br) bem como nas reuniões do grupo. Possui também um blog em http://cidadaocarioca.blogspot.com |
|
|
|
|
| Cache Substitution : Novos truques com cache | |
|
|
|
Para começar, vamos fazer uma pequena demonstração :
1) Crie uma nova aplicação web
2) Crie um webControl chamado "Timer.ascx"
3) Insira um label no user control
4) Insira o seguinte código no load :
66 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
67
68
69 Label1.Text = Now.ToLongTimeString
70
71 End Sub
5) Arraste o controle para a página default.ASPX
6) Na página default.aspx insira a tag de controle de cache :
<%@ OutputCache Duration="30" VaryByParam="*" %>
7) Teste a aplicação. Apesar do user control não ter tag de cache, ficará em cache por 30 segundos, só atualizando o relógio de 30 em 30 segundos.
8) Insira a seguinte tag de cache no user control :
<%@ OutputCache Duration="5" VaryByParam="*" %>
Conclusão : O user control não pode ter uma variação de cache superior a da página. Não pode variar mais que a página. O cache parcial, ou seja, a aplicação de cache em user controls, funciona para casos em que o user control ficará em cache enquanto o resto da página será processada, mas é impossível haver casos em que a página fique em cache enquanto o user control é processado.
Casos como exibição de data e hora, exibição do login do usuário e outras informações simples como essas acabam criando uma situação complicada. Isso pode ser resolvido dividindo-se a página em diversos user controls e utilizando um cache diferenciado para cada um deles, mas é trabalhoso.
Para resolver este problema o ASP.NET 2.0 traz o conceito de cache substitution, ou seja, a capacidade de substituir pedaços de uma página que encontra-se em cache.
Vamos fazer um exemplo, ver como funciona :
1) Insira o controle substitution na página. Este webControl encontra-se na toolbox.
2) Configure a propriedade MethodName como ExibirHora
3) Crie o método ExibirHora da seguinte forma :
74 Public Shared Function ExibirHora(ByVal context As HttpContext) As String
75
76 Return (Now.ToLongTimeString)
77
78 End Function
Observe que o método precisar ser shared pois não existirá instância da página quando este método for executado.
Nossa página, no momento, ficou assim :
A forma básica como acabamos de ver pode atender a muitos casos, mas não todos. Para atender a casos mais complexos O cache substitution nos traz dois desafios :
1) Seria muito dificil montar conteudo mais complexo, com mais dados a serem exibidos, já que teríamos que fazer a montagem do HTML.
2) Não existe controle de cache para o conteúdo substituido. A substituição acontecerá sempre. Para conteúdos simples, isso pode não ter impacto, mas para conteúdos maiores a falta de controle de cache é uma perda significativa.
Vamos resolver este problema com mais um exemplo, continuando o que fizemos anteriormente :
1) Retire a tag de cache do user control Timer
2) Crie uma nova página, "Vazio.aspx"
3) Entrando no HTML, apague todo o conteúdo, deixando apenas a tag @Page
4) No código, monte o seguinte no evento Load :
80 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
81
82 Me.Controls.Add(Me.LoadControl(Request.QueryString("ct")))
83
84 End Sub
Desta forma a Vazio.aspx estará esperando receber um parâmetro "CT" na querystring. Irá carregrar um usercontrol conforme o parâmetro recebido, o user control será o único objeto contido na página
5) Altere a ExibirHora para que fique da seguinte forma :
86 Public Shared Function ExibirHora(ByVal context As HttpContext) As String
87
88 If IsNothing(context.Cache("timer")) Then
89
90 Dim resultado As String
91 Dim wc As New Net.WebClient
92 resultado = wc.DownloadString("http://" & context.Request.Url.Authority & context.Request.ApplicationPath & "/vazio.aspx?ct=timer.ascx")
93
94 context.Cache.Insert("timer", resultado, Nothing, Now.AddSeconds(5), System.Web.Caching.Cache.NoSlidingExpiration)
95
96 End If
97
98 Return (context.Cache("timer"))
99 End Function
Com esta função resolvemos os dois problemas que citamos anteriormente. Quanto ao cache, assumimos o total controle do cache : Guardamos o conteúdo que iremos exibir em uma variável no cache chamada Timer. Controlamos o tempo de vida desta variável utilizando os recursos do objeto Cache : A variável viverá por 5 segundos.
Apenas iremos processar a geração do conteúdo se a variável houver sido destruida, dai nosso teste com isNothing, com isso geramos um cache de 5 segundos em nosso exemplo.
Quanto ao processamento, é feito com uma chamada para a página vazio.aspx, utilizando a classe webClient. É uma chamada web a parte que resulta do HTML de nosso user control, sendo isso inserido no webControl substitution.
É óbvio que para um simples webControl com a hora atual é simples demais para esta implementação, nosso primeiro exemplo ficou muito mais simples. Mas o uso do webControl como neste último exemplo nos dá a liberdade de gerarmos um conteúdo maior e mais complexo, permitindo que o conteúdo varie enquanto a página estiver em cache, graças ao recurso de substituição.
Por fim : Rodando a aplicação você verá que a primeira exibição da hora será atualizada a cada 30 segundos, devido ao cache da página, enquanto que a 2a exibição da hora será atualizada a cada 5 segundos, devido a nossa substituição.
Outros artigos sobre cache :
http://www.bufaloinfo.com.br/artigos/coluna29.asp
http://www.bufaloinfo.com.br/artigos/coluna11.asp