母版页缓存问题

Asp.net缓存技术是一项非常重要的技术。当某个页面被频繁访问时,如果不适用缓存技术,那么,每访问一次就要回发一次服务器,显然这样对服务器造成很大的负担。所以,可以在被频繁访问的页面中设置缓存,不仅仅可以在普通页面设置缓存,也可以在母版页中设置缓存,从而提高网站的性能。

应注意的是不应该把高速缓存只用到母版页,不能把outputcache指令放到母版页上。如果这样,在页面第二次检索时就会出错,因为程序找不到缓存的页面。所以,为了能让母版页输出高速缓存,应该把outputcache指令放到内容页上,这会高速缓存内容页面的内容和母版页的内容。通过outputcache指令在内容页中实现缓存的关键代码如下:

<%@ OutputCache Duration="10" VaryByParam="none" %>

有时缓存整个页面是不现实的,因为页的某些部分可能在每次请求时都需要变化。在这些情况下,只能缓存页的一部分。顾名思义,页面部分缓存是将页面部分内容 保存在内存中以便响应用户请求,而页面其他部分内容则为动态内容。页面部分缓存的实现包括两种方式:控件缓存和替换后缓存。

在控件缓存(也称为片段缓存)中,可以通过创建用户控件来包含缓存的内容,然后将用户控件标记为可缓存来缓存部分页输出。该选项允许缓存页中的特定 内容,而在每次都重新创建整个页。例如,如果创建的页显示大量动态内容(如股票信息),但也有某些部分是静态的(如每周摘要),则可以在用户控件中创建这 些静态部分并将用户控件配置为缓存。

缓存后替换与控件缓存正好相反。它对页进行缓存,但是页中的某些片段是动态的,因此不会缓存这些片 段。例如,如果创建的页在设定的时间段内完全是静态的(例如新闻报道页),可以设置为缓存整个页。如果为缓存的页添加旋转广告横幅,则在页请求之间,广告 横幅不会变化。然而,使用缓存后替换,可以对页进行缓存,但可以将特定部分标记为不可缓存。在本例中,将广告横幅标记为不可缓存。它们将在每次页请求时动 态创建,并添加到缓存的页输出中。

控件缓存

通过创建用户控件来缓存内容,可以将页上需要花费宝贵的处理器时间来创建的某些部分(例如数据库查询)与页的其他部分分离开。只需占用很少服务器资源的部分可以在每次请求时动态生成。

在标识了要缓存的页的部分,并创建了用以包含这些部分中的每个部分的用户控件后,您必须确定这些用户控件的缓存策略。您可以使用 @ OutputCache 指令,或者在代码中使用 PartialCachingAttribute 类,以声明的方式为用户控件设置这些策略。

例如,如果在用户控件文件(.ascx 文件)的顶部包括下面的指令,则该控件的一个版本将在输出缓存中存储 120 秒。

<%@ OutputCache Duration="120" VaryByParam="None" %>

若要在代码中设置缓存参数,可以在用户控件的类声明中使用一个属性。例如,如果在类声明的元数据中包括下面的属性,则该内容的一个版本将在输出缓存中存储 120 秒:

C#

[PartialCaching(120)]

public partial class CachedControl : System.Web.UI.UserControl

{

// Class Code

}

 

注意

由于可在页上嵌套用户控件,您还可以嵌套已放置到输出缓存中的用户控件。可以为页和嵌套的用户控件指定不同的缓存设置。

以编程方式引用缓存的用户控件

在以声明的方式创建可缓存的用户控件时,可以包括一个 ID 属性,以便以编程方式引用该用户控件实例。但是,在代码中引用用户控件之前,必须验证在输出缓存中是否存在该用户控件。缓存的用户控件只在首次请求时动态 生成;在指定的时间到期之前,从输出缓存满足所有的后续请求。确定用户控件已实例化后,可以从包含页以编程方式操作该用户控件。例如,如果通过声明方式将 SampleUserControl 的 ID 分配给用户控件,则可以使用下面的代码检查它是否存在。

C#

protected void Page_Load(object sender, EventArgs e)

{

if (SampleUserControl != null)

// Place code manipulating SampleUserControl here.

}

以不同的持续时间缓存页和用户控件

可 以为页和页上的用户控件设置不同的输出缓存持续时间值。如果页的输出缓存持续时间长于用户控件的输出缓存持续时间,则页的输出缓存持续时间优先。例如,如 果页的输出缓存设置为 100 秒,而用户控件的输出缓存设置为 50 秒,则包括用户控件在内的整个页将在输出缓存中存储 100 秒,而与用户控件较短的时间设置无关。

下面的代码示例演示了当页的缓存持续时间长于用户控件的缓存持续时间时的效果。该页配置为缓存 100 秒。

C#

<%@ Page language="C#" %>

<%@ Register tagprefix="SampleControl" tagname="Time" src="uc01.ascx" %>

<%@ OutputCache duration="100" varybyparam="none" %>

 

<SampleControl:Time runat="server" /><br /> <br /> <br />

 

This page was most recently generated at:<p>

 

<% DateTime t = DateTime.Now.ToString();

Response.Write(t); %>

下面的代码示例演示了包括在页中的用户控件。控件的缓存持续时间设置为 50 秒。

C#

<% @Control language="C#" %>

<% @OutputCache duration="50" varybyparam="none" %>

 

This user control was most recently generated at:<p>

<% DateTime t = DateTime.Now.ToString();

Response.Write(t); %>

不过,如果页的输出缓存持续时间比用户控件的输出缓存持续时间短,则即使已为某个请求重新生成该页的其余部分,也将一直缓存用户控件直到其持续 时间到期为止。例如,如果页的输出缓存设置为 50 秒,而用户控件的输出缓存设置为 100 秒,则页的其余部分每到期两次,用户控件才到期一次。

下面的代码演示了一个页的标记,该页中包含的用户控件的缓存持续时间长于该页的缓存持续时间。该页配置为缓存 50 秒。

C#

<%@ Page language="C#" %>

<%@ Register tagprefix="SampleControl" tagname="Time" src="uc2.ascx" %>

<%@ OutputCache duration="50" varybyparam="none" %>

 

<SampleControl:Time runat="server" /><br /> <br /> <br />

 

This page was most recently generated at:<p>

<% DateTime t = DateTime.Now.ToString();

Response.Write(t); %>

下面的代码演示了包括在页中的用户控件。控件的缓存持续时间设置为 100 秒。

C#

<% @Control language="C#" %>

<% @OutputCache duration="100" varybyparam="none" %>

 

This user control was most recently generated at:<p>

 

<% DateTime t = DateTime.Now.ToString();

Response.Write(t); %>

对页面进行缓存可以大大提高 Web 应用程序的性能。不过,在有些情况下,需要缓存页面的大部分内容,但页面中的某些片段是动态的。例如,如果创建一个页面,其中的新闻故事在设定时间段内完 全是静态的,则可以设置为缓存整个页面。如果希望提供在每次页请求时都发生变化的交替出现的广告横幅,则该页中包含该广告的部分需要是动态的。

若要允许缓存某个页面但动态地替换其中的某些内容,可以使用 ASP.NET 缓存后替换。通过使用缓存后替换,将对整个页面进行输出缓存,并将特定的部分标记为不进行缓存。在广告横幅示例中,AdRotator 控件使您可以利用缓存后替换功能,以便为每个用户及在每次刷新页时动态创建广告。

有三种方法可以实现缓存后替换:

  • 以声明方式使用 Substitution 控件。
  • 以编程方式使用 Substitution 控件 API。
  • 以隐式方式使用 AdRotator 控件。

Substitution 控件

ASP.NET Substitution 控件指定缓存页中动态创建而不进行缓存的部分。将 Substitution 控件放置在该页上要显示动态内容的位置。

在运行时,Substitution 控件调用使用 MethodName 属性指定的方法。该方法必须返回一个字符串,然后该字符串替换 Substitution 控件的内容。该方法必须是 PageUserControl 包含控件上的静态方法。

使用 Substitution 控件可以将客户端可缓存性更改为服务器可缓存性,以便该页面不会在客户端上进行缓存。这样可以确保以后对该页的请求能够再次调用该方法以生成动态内容。

Substitution API

若要以编程方式为缓存页创建动态内容,可以在页代码中将某个方法的名称作为参数传递给 WriteSubstitution 方法来调用该方法。该方法处理动态内容的创建,它采用单个 HttpContext 参数并返回一个字符串。该返回字符串是将在给定位置被替换的内容。通过调用 WriteSubstitution 方法来代替以声明方式使用 Substitution 控件的一个好处是可以调用任意对象的方法,而不只是调用 PageUserControl 对象的静态方法。

调用 WriteSubstitution 方法可以将客户端可缓存性更改为服务器可缓存性,以便该页不会在客户端上进行缓存。这样可以确保以后对该页的请求能够再次调用该方法以生成动态内容。

AdRotator 控件

AdRotator 服务器控件在内部实现对缓存后替换的支持。如果将 AdRotator 控件放在页面上,则无论是否缓存父页,都将在每次请求时呈现其特有的广告。因此,包含 AdRotator 控件的页面只在服务器端进行缓存。

总结:这几句才是最重要的,没耐心的人是看不到了,首先按照最上面所说在每一个页面都加缓存标记很繁琐,其次那样会导致整个页面都被缓存,从而导致应该时时更新的东西没办法第一时间显示,而缓存后替换很不给力,微软设计这个的时候真是一个败笔。最后我用的解决方法是在把母版页里的东西全部扔到自定义控件里去,然后在自定义控件里设置缓存,这样在外边无需任何修改,就圆满的解决问题了,代码我会传到爱特的实验室里去,你们可以去看看。

代码:

C1.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="c1.ascx.cs" Inherits="c1" %>

<%@ OutputCache Duration="10" VaryByParam="none" %>

<div>

页面缓存的时间:<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>

</div>

 

C1.ascx.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

 

public partial class c1 : System.Web.UI.UserControl

{

protected void Page_Load(object sender, EventArgs e)

{

Label1.Text = DateTime.Now.ToString();

}

}

Cache.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="cache.aspx.cs" Inherits="cache" %>

 

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">

</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

<asp:Substitution ID="Substitution1" runat="server" />

<div>

真实(替换)的时间:<asp:Label ID="Label1" runat="server" ></asp:Label>

</div>

</asp:Content>

 

 

Cache.aspx.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

 

public partial class cache : System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

Label1.Text = DateTime.Now.ToString();

}

}

MasterPage.master

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>

 

<%@ Register Src="~/c1.ascx" TagPrefix="uc1" TagName="c1" %>

 

 

<!DOCTYPE html>

 

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title></title>

 

<asp:ContentPlaceHolder ID="head" runat="server">

</asp:ContentPlaceHolder>

</head>

<body>

<form id="form1" runat="server">

<uc1:c1 runat="server" ID="c1" />

<div>

<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">

</asp:ContentPlaceHolder>

</div>

</form>

</body>

</html>

posted @ 2013-05-25 23:19  血之君殇  阅读(733)  评论(0编辑  收藏  举报