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

在之前的文章中我们讨论了MVC中使用页面缓存的一些方法,而其中由于页面缓存的粒度太粗,不能对页面进行局部的缓存,或者说,如果我们想在页面缓存的同时对局部进行动态输出该怎么办?下面我们看下这类问题的处理。 <!--more-- MVC 有一个Post-cache substitution的东西,可以对缓存的内容进行替换。

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

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

使用Post-Cache Substitution

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

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

{% codeblock lang:csharp%} 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\

                {\

                    “Gas prices go up!”,\

                    “Life discovered on Mars!”,\

                    “Moon disappears!”\

                };\

            var rnd = new Random();\

            return news[rnd.Next(news.Count)];\

        }\

    } {% endcodeblock %}

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

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

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