MVC3缓存之二:页面缓存中的局部动态

上一篇我们讨论了MVC中使用页面缓存的一些方法,而其中由于页面缓存的粒度太粗,不能对页面进行局部的缓存,或者说,如果我们想在页面缓存的同时对局部进行动态输出该怎么办?下面我们看下这类问题的处理。

MVC中有一个Post-cache substitution的东西,可以对缓存的内容进行替换。 

使用Post-Cache Substitution

 

  • 定义一个返回需要显示的动态内容string的方法。
  • 调用HttpResponse.WriteSubstitution()方法即可。

 

示例,我们在Model层中定义一个随机返回新闻的方法。

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

}  

然后在页面中需要动态显示内容的地方调用。

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

如在上一篇文章中说明的那样,给Controller加上缓存属性。

using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    [HandleError]
    
public class HomeController : Controller
    {
        [OutputCache(Duration
=60, VaryByParam="none")]
        
public ActionResult Index()
        {
            
return View();
        }
    }

}

可以发现,程序对整个页面进行了缓存60s的处理,但调用WriteSubstitution方法的地方还是进行了随机动态显示内容。

对Post-Cache Substitution的封装

将静态显示广告Banner的方法封装在AdHelper中。

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

这样在页面中只要进行这样的调用,记得需要在头部导入命名空间。

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

使用这样的方法可以使得内部逻辑对外呈现出更好的封装。

posted @ 2011-03-29 11:08 Parry 阅读(...) 评论(...) 编辑 收藏