Condividi tramite


Aggiunta di contenuto dinamico a una pagina memorizzata nella cache (C#)

di Microsoft

Informazioni su come combinare contenuto dinamico e memorizzato nella cache nella stessa pagina. La sostituzione post-cache consente di visualizzare contenuto dinamico, ad esempio annunci banner o notizie, all'interno di una pagina memorizzata nella cache.

Sfruttando la memorizzazione nella cache dell'output, è possibile migliorare notevolmente le prestazioni di un'applicazione MVC ASP.NET. Anziché rigenerare una pagina ogni e ogni volta che viene richiesta la pagina, la pagina può essere generata una sola volta e memorizzata nella cache per più utenti.

Ma c'è un problema. Cosa accade se è necessario visualizzare il contenuto dinamico nella pagina? Si supponga, ad esempio, di voler visualizzare un banner pubblicitario nella pagina. Non vuoi che l'annuncio banner venga memorizzato nella cache in modo che ogni utente veda lo stesso annuncio. Non farete soldi così!

Fortunatamente, c'è una soluzione semplice. È possibile sfruttare una funzionalità del framework ASP.NET denominato sostituzione post-cache. La sostituzione post-cache consente di sostituire il contenuto dinamico in una pagina memorizzata nella cache in memoria.

In genere, quando si restituisce nella cache una pagina usando l'attributo [OutputCache], la pagina viene memorizzata nella cache sia nel server che nel client (il Web browser). Quando si usa la sostituzione post-cache, una pagina viene memorizzata nella cache solo nel server.

Uso della sostituzione post-cache

L'uso della sostituzione post-cache richiede due passaggi. Prima di tutto, è necessario definire un metodo che restituisce una stringa che rappresenta il contenuto dinamico da visualizzare nella pagina memorizzata nella cache. Chiamare quindi il metodo HttpResponse.WriteSubstitution() per inserire il contenuto dinamico nella pagina.

Si supponga, ad esempio, di voler visualizzare in modo casuale notizie diverse in una pagina memorizzata nella cache. La classe nell'elenco 1 espone un singolo metodo, denominato RenderNews(), che restituisce in modo casuale un elemento di notizie da un elenco di tre notizie.

Elenco 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)];
        }
    }
}

Per sfruttare i vantaggi della sostituzione post-cache, chiamare il metodo HttpResponse.WriteSubstitution(). Il metodo WriteSubstitution() configura il codice per sostituire un'area della pagina memorizzata nella cache con contenuto dinamico. Il metodo WriteSubstitution() viene usato per visualizzare l'elemento di notizie casuale nella visualizzazione nell'elenco 2.

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

Il metodo RenderNews viene passato al metodo WriteSubstitution(). Si noti che il metodo RenderNews non viene chiamato (non sono presenti parentesi). Viene invece passato un riferimento al metodo a WriteSubstitution().

La visualizzazione Indice viene memorizzata nella cache. La visualizzazione viene restituita dal controller nell'elenco 3. Si noti che l'azione Index() è decorata con un attributo [OutputCache] che fa sì che la visualizzazione Indice venga memorizzata nella cache per 60 secondi.

Elenco 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();
        }
    }
}

Anche se la visualizzazione Indice è memorizzata nella cache, vengono visualizzate notizie casuali diverse quando si richiede la pagina Indice. Quando si richiede la pagina Indice, l'ora visualizzata dalla pagina non cambia per 60 secondi (vedere la figura 1). Il fatto che l'ora non cambia dimostra che la pagina viene memorizzata nella cache. Tuttavia, il contenuto inserito dal metodo WriteSubstitution(), ovvero l'elemento di notizie casuale, cambia con ogni richiesta .

Figura 1: Inserimento di notizie dinamiche in una pagina memorizzata nella cache

clip_image002

Uso della sostituzione post-cache nei metodi helper

Un modo più semplice per sfruttare la sostituzione post-cache consiste nell'incapsulare la chiamata al metodo WriteSubstitution() all'interno di un metodo helper personalizzato. Questo approccio è illustrato dal metodo helper nell'elenco 4.

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

L'elenco 4 contiene una classe statica che espone due metodi: RenderBanner() e RenderBannerInternal(). Il metodo RenderBanner() rappresenta il metodo helper effettivo. Questo metodo estende la classe Standard ASP.NET MVC HtmlHelper in modo da poter chiamare Html.RenderBanner() in una visualizzazione esattamente come qualsiasi altro metodo helper.

Il metodo RenderBanner() chiama il metodo HttpResponse.WriteSubstitution() passando il metodo RenderBannerInternal() al metodo WriteSubstitution().

Il metodo RenderBannerInternal() è un metodo privato. Questo metodo non verrà esposto come metodo helper. Il metodo RenderBannerInternal() restituisce in modo casuale un'immagine di annuncio banner da un elenco di tre immagini di annunci banner.

La visualizzazione Indice modificata in Listato 5 illustra come è possibile utilizzare il metodo helper RenderBanner(). Si noti che nella parte superiore della visualizzazione è inclusa una direttiva %@ Import %> aggiuntiva <per importare lo spazio dei nomi MvcApplication1.Helpers. Se non si importa questo spazio dei nomi, il metodo RenderBanner() non verrà visualizzato come metodo nella proprietà Html.

Listato 5 : Views\Home\Index.aspx (con il metodo 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 si richiede il rendering della pagina dalla visualizzazione nell'elenco 5, viene visualizzato un annuncio banner diverso con ogni richiesta (vedere la figura 2). La pagina viene memorizzata nella cache, ma l'annuncio banner viene inserito dinamicamente dal metodo helper RenderBanner().

Figura 2: visualizzazione Indice che visualizza un banner casuale

clip_image004

Riepilogo

Questa esercitazione ha illustrato come aggiornare dinamicamente il contenuto in una pagina memorizzata nella cache. Si è appreso come usare il metodo HttpResponse.WriteSubstitution() per abilitare l'invio di contenuto dinamico in una pagina memorizzata nella cache. Si è anche appreso come incapsulare la chiamata al metodo WriteSubstitution() all'interno di un metodo helper HTML.

Sfruttare la memorizzazione nella cache quando possibile: può avere un impatto significativo sulle prestazioni delle applicazioni Web. Come illustrato in questa esercitazione, è possibile sfruttare la memorizzazione nella cache anche quando è necessario visualizzare contenuto dinamico nelle pagine.