Adicionar conteúdo dinâmico a uma página em cache (C#)
pela Microsoft
Saiba como misturar conteúdo dinâmico e armazenado em cache na mesma página. A substituição pós-cache permite exibir conteúdo dinâmico, como anúncios em faixa ou itens de notícias, em uma página que foi armazenada em cache.
Aproveitando o cache de saída, você pode melhorar drasticamente o desempenho de um aplicativo MVC ASP.NET. Em vez de regenerar uma página cada vez que a página é solicitada, a página pode ser gerada uma vez e armazenada em cache na memória para vários usuários.
Mas há um problema. E se você precisar exibir conteúdo dinâmico na página? Por exemplo, imagine que você deseja exibir um anúncio de faixa na página. Você não quer que o anúncio de faixa seja armazenado em cache para que todos os usuários vejam o mesmo anúncio. Você não ganharia dinheiro assim!
Felizmente, há uma solução fácil. Você pode aproveitar um recurso da estrutura ASP.NET chamada substituição pós-cache. A substituição pós-cache permite substituir o conteúdo dinâmico em uma página que foi armazenada em cache na memória.
Normalmente, quando você gera um cache de uma página usando o atributo [OutputCache], a página é armazenada em cache no servidor e no cliente (o navegador da Web). Quando você usa a substituição pós-cache, uma página é armazenada em cache somente no servidor.
Usando substituição pós-cache
O uso da substituição pós-cache requer duas etapas. Primeiro, você precisa definir um método que retorna uma cadeia de caracteres que representa o conteúdo dinâmico que você deseja exibir na página armazenada em cache. Em seguida, chame o método HttpResponse.WriteSubstitution() para injetar o conteúdo dinâmico na página.
Imagine, por exemplo, que você deseja exibir aleatoriamente diferentes itens de notícias em uma página armazenada em cache. A classe na Listagem 1 expõe um único método, chamado RenderNews(), que retorna aleatoriamente um item de notícias de uma lista de três itens de notícias.
Listagem 1 – Models\News.cs
using System;
using System.Collections.Generic;
using System.Web;
namespace MvcApplication1.Models
{
public class News
{
public static string RenderNews(HttpContext context)
{
var news = new List<string>
{
"Gas prices go up!",
"Life discovered on Mars!",
"Moon disappears!"
};
var rnd = new Random();
return news[rnd.Next(news.Count)];
}
}
}
Para aproveitar a substituição pós-cache, chame o método HttpResponse.WriteSubstitution(). O método WriteSubstitution() configura o código para substituir uma região da página armazenada em cache por conteúdo dinâmico. O método WriteSubstitution() é usado para exibir o item de notícias aleatório no modo de exibição na Listagem 2.
Listagem 2 – Views\Home\Index.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Index</title>
</head>
<body>
<div>
<% Response.WriteSubstitution(News.RenderNews); %>
<hr />
The content of this page is output cached.
<%= DateTime.Now %>
</div>
</body>
</html>
O método RenderNews é passado para o método WriteSubstitution(). Observe que o método RenderNews não é chamado (não há parênteses). Em vez disso, uma referência ao método é passada para WriteSubstitution().
A exibição Índice é armazenada em cache. O modo de exibição é retornado pelo controlador na Listagem 3. Observe que a ação Index() é decorada com um atributo [OutputCache] que faz com que a exibição Índice seja armazenada em cache por 60 segundos.
Listagem 3 – Controllers\HomeController.cs
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
[OutputCache(Duration=60, VaryByParam="none")]
public ActionResult Index()
{
return View();
}
}
}
Embora a exibição Índice esteja armazenada em cache, diferentes itens de notícias aleatórias são exibidos quando você solicita a página Índice. Quando você solicita a página Índice, o tempo exibido pela página não é alterado por 60 segundos (consulte a Figura 1). O fato de que a hora não é alterada prova que a página está armazenada em cache. No entanto, o conteúdo injetado pelo método WriteSubstitution() – o item de notícias aleatório – é alterado com cada solicitação .
Figura 1 – Injetar itens de notícias dinâmicas em uma página armazenada em cache
Usando substituição pós-cache em métodos auxiliares
Uma maneira mais fácil de aproveitar a substituição pós-cache é encapsular a chamada para o método WriteSubstitution() dentro de um método auxiliar personalizado. Essa abordagem é ilustrada pelo método auxiliar na Listagem 4.
Listagem 4 – AdHelper.cs
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
namespace MvcApplication1.Helpers
{
public static class AdHelper
{
public static void RenderBanner(this HtmlHelper helper)
{
var context = helper.ViewContext.HttpContext;
context.Response.WriteSubstitution(RenderBannerInternal);
}
private static string RenderBannerInternal(HttpContext context)
{
var ads = new List<string>
{
"/ads/banner1.gif",
"/ads/banner2.gif",
"/ads/banner3.gif"
};
var rnd = new Random();
var ad = ads[rnd.Next(ads.Count)];
return String.Format("<img src='{0}' />", ad);
}
}
}
A listagem 4 contém uma classe estática que expõe dois métodos: RenderBanner() e RenderBannerInternal(). O método RenderBanner() representa o método auxiliar real. Esse método estende o padrão ASP.NET classe HtmlHelper MVC para que você possa chamar Html.RenderBanner() em uma exibição como qualquer outro método auxiliar.
O método RenderBanner() chama o método HttpResponse.WriteSubstitution() passando o método RenderBannerInternal() para o método WriteSubstitution().
O método RenderBannerInternal() é um método privado. Esse método não será exposto como um método auxiliar. O método RenderBannerInternal() retorna aleatoriamente uma imagem de anúncio de faixa de uma lista de três imagens de anúncio em faixa.
A exibição Índice modificada na Listagem 5 ilustra como você pode usar o método auxiliar RenderBanner(). Observe que uma <diretiva %@ adicional de %> de importação está incluída na parte superior da exibição para importar o namespace MvcApplication1.Helpers. Se você não importar esse namespace, o método RenderBanner() não aparecerá como um método na propriedade Html.
Listagem 5 – Views\Home\Index.aspx (com o método RenderBanner()
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<%@ Import Namespace="MvcApplication1.Helpers" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Index</title>
</head>
<body>
<div>
<% Response.WriteSubstitution(News.RenderNews); %>
<hr />
<% Html.RenderBanner(); %>
<hr />
The content of this page is output cached.
<%= DateTime.Now %>
</div>
</body>
</html>
Quando você solicita a página renderizada pelo modo de exibição na Listagem 5, um anúncio de faixa diferente é exibido com cada solicitação (consulte a Figura 2). A página é armazenada em cache, mas o anúncio de faixa é injetado dinamicamente pelo método auxiliar RenderBanner().
Figura 2 – A exibição Índice exibindo um anúncio de faixa aleatória
Resumo
Este tutorial explicou como você pode atualizar dinamicamente o conteúdo em uma página armazenada em cache. Você aprendeu a usar o método HttpResponse.WriteSubstitution() para permitir que o conteúdo dinâmico seja injetado em uma página armazenada em cache. Você também aprendeu a encapsular a chamada para o método WriteSubstitution() em um método auxiliar HTML.
Aproveite o cache sempre que possível – isso pode ter um impacto dramático no desempenho de seus aplicativos Web. Conforme explicado neste tutorial, você pode aproveitar o cache mesmo quando precisar exibir conteúdo dinâmico em suas páginas.