生成高性能、可缩放的 Web 应用程序最重要的因素之一是能够在首次请求项时将这些项存储在内存中,不管它们是数据对象、页还是页的某些部分。可以将这些项存储在 Web 服务器上或请求流中的其他软件上,例如代理服务器或浏览器。使您能够避免重新创建满足先前请求的信息,尤其是那些需要大量处理器时间或资源的信息。这就是通常所说的缓存,它允许您使用多种技术跨 HTTP 请求存储页输出或应用程序数据并对其进行重复使用。这样,服务器不需要重新创建信息,从而节省了时间和资源。
ASP.NET 提供了两种您可以用来创建高性能 Web 应用程序的缓存类型。第一种叫做输出缓存,它允许将动态页或用户控件响应存储在输出流(从发起服务器到请求浏览器)中任何具备 HTTP 1.1 缓存功能的设备上。当后面的请求发生时,不执行页或用户控件代码,缓存的输出用于满足该请求。第二种类型的缓存是传统的应用程序数据缓存,可以使用它以编程方式将任意对象(例如数据集)存储到服务器内存,这样您的应用程序可以节省重新创建这些对象所需的时间和资源。
设置页缓存的到期时间
若要将页添加到输出缓存中,您必须建立该页的到期策略。您可以使用 @ OutputCache 指令以声明方式完成该操作,或使用 HttpCachePolicy.SetExpires 方法以编程方式完成该操作。默认情况下,@ OutputCache 指令将 Cache-Control 标头设置为 Public。
如果以编程方式为页设置到期时间,则您还必须为缓存的页设置 Cache-Control 标头。使用 HttpCachePolicy.SetCacheability 方法将 HttpCacheability 枚举设置为 Public。
以声明方式为页设置输出缓存到期时间
- 将 @ OutputCache 指令包含在要将其响应存储在输出缓存中的页(.aspx 文件)中。该指令必须包括一个 Duration 属性(该属性具有正数字值)和一个 VaryByParam 属性。下面的 @ OutputCache 指令将页的到期时间设置为 60 秒。
<%@ OutputCache Duration="60" VaryByParam="None" %>
注意 当使用 @ OutputCache 指令时,您必须包括一个 VaryByParam 属性,否则将发生分析器错误。如果不想使用 VaryByParam 属性所提供的功能,请将其值设置为 None。有关使用 VaryByParam 属性的更多信息,请参见缓存页的多个版本。
以编程方式为页设置输出缓存到期时间
- 在页的代码声明块中或在该页的代码隐藏类中,通过使用 Response.Cache 语法将设置该页到期策略的代码包括在其中。下面的示例设置页的到期时间,如上一个过程中 @ OutputCache 指令所进行的操作。
- [C#]
- Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
- Response.Cache.SetCacheability(HttpCacheability.Public);
- Response.Cache.SetValidUntilExpires(true);
一旦超过了缓存页的持续时间,后面对该页的请求将导致动态生成的响应。又会在一段指定的持续时间内缓存该响应页。
页或用户控件的可缓存性定义可以在什么样的 HTTP 1.1 Internet 设备上缓存文档。这些设备包括发出请求的客户端,响应请求的 Web 服务器,以及请求或响应流中任何具有缓存功能的设备(例如代理服务器)。当 Web 服务器发送响应时,在它传递的所有信息中包括一个 Cache-Control HTTP 标头,该标头定义可在其上缓存文档的设备。ASP.NET 在 HttpCacheability 枚举中定义这些值。该枚举具有六个值,其中四个值直接映射为 Cache-Control HTTP 标头设置,另外两个特殊值分别为 HttpCacheability.ServerAndPrivate 和 HttpCacheability.ServerAndNoCache。ServerAndPrivate 只允许将响应缓存在原服务器和请求客户端上。而 ServerAndNoCache 只允许将响应缓存在原服务器上。
根据应用程序的需要,您可以选择定义哪些设备可以缓存特定的页,哪些设备不能缓存特定的页。例如,您可能希望用户登录页的可缓存性设置不同于显示产品选择的目录页。对于登录页,出于安全方面的考虑,您可能希望只将页缓存在服务器上,而目录页可以缓存在任何支持缓存的设备上。
通过将 Location 属性包括在 @ OutputCache 指令中并指定一个 OutputCacheLocation 枚举值,可以以声明方式设置页输出的可缓存性。
通过使用 HttpCachePolicy.SetCacheability 方法指定页的 HttpCacheability 值,您可以以编程方式设置页输出的可缓存性。通过 HttpResponse.Cache 属性可以访问该方法,而使用页的代码隐藏类或代码声明块中的 Response.Cache 语法可以访问该属性。
注意 如果使用 @ OutputCache 指令设置页的可缓存性,则您必须连同 Location 属性一起声明 Duration 和 VaryByParam 属性。必须将 Duration 属性设置为大于零的值。如果您不想使用 VaryByParam 属性所提供的功能,则可以将其属性设置为 none。有关更多信息,请参见设置页缓存的到期时间和缓存页的多个版本。
相比之下,如果使用 HttpCachePolicy 类设置可缓存性,如果已建立了验证策略,则您不需要设置到期时间。
以声明方式设置页的可缓存性
- 将 @ OutputCache 指令包括在 .aspx 文件中并定义必需的 Duration 和 VaryByParam 属性。
- 将 Location 属性包括在 @ OutputCache 指令中并将其值定义为受支持的值之一。这些值包括 Any、Client、Downstream、Server 或 None。
注意 默认值为 Any。如果未定义 Location 属性,则可以将页输出缓存在与响应有关的所有具有缓存功能的网络应用程序上。其中包括请求客户端、原服务器、以及响应通过的任何代理服务器。
以编程方式设置页的可缓存性
- 在页的代码声明块或代码隐藏类文件中,使用 Response.Cache 语法来访问 HttpCachePolicy.SetCacheability 方法。下面的代码将 Cache-Control HTTP 标头设置为 Public。
- [C#]
- Response.Cache.SetCacheability(HttpCacheability.Public);
注意 如果将可缓存性设置为 HttpCacheability.NoCache 或 HttpCacheability.ServerAndNoCache,则请求的客户端不会将页缓存在其“历史记录”文件夹中。例如,用户无论何时单击向后或向前按钮,都请求响应的新版本。通过将 HttpCachePolicy.SetAllowResponseInBrowserHistory 方法设置为 true,可以重写此行为。
[C#]
Response.Cache.SetAllowResponseInBrowserHistory(true);
如果将可缓存性设置为 NoCache 或 ServerAndNoCache 以外的其他任何值,则 ASP.NET 将忽略 SetAllowResponseInBrowserHistory 方法所设置的值。
当输出缓存中有一个它希望用作客户端请求响应的现有项时,它必须首先检查原服务器(或含有新响应的中间缓存,如代理服务器)以确定该缓存项是否仍可用。此过程称为验证缓存项。为避免因在缓存项有效的情况下重新生成和重新传输页,或在缓存项无效的情况下发生额外的往返进程而导致资源浪费, ASP.NET 为您提供了一种以编程方式验证缓存页的机制。
注意 有关缓存有效性及其要求的更多信息,请参见位于 www.w3.orgor 的 HTTP 1.1 规范。
若要确定缓存页是否有效,必须使用与 HttpCacheValidateHandler 委托相同的签名定义一个事件处理程序。该处理程序应执行检查以确定存储在缓存中的页是否仍有效,然后将 HttpValidationStatus 枚举值之一分配给检查的可能返回结果。该枚举具有以下三个值:
- Invalid,该值表示缓存页无效,并且将从缓存中移除该页,而该请求将被作为缓存未命中处理。
- IgnoreThisRequest,该值导致请求被作为缓存未命中处理,并且将执行该页,但该缓存页是无效的。
- Valid,该值表示缓存页仍有效。
在一个页生存期事件中,HttpCachePolicy.AddValidationCallback 方法将事件处理程序作为参数获取。从 Web 服务器缓存中输出响应服务之前,将查询已注册的所有处理程序以确保资源的有效性。如果任何处理程序设置了表示资源无效的标志,则该项将标记为无效并将从缓存中移除。然后,将请求作为缓存未命中来处理。
检查缓存页的有效性
- 定义类型 HttpCacheValidateHandler 的事件处理程序,该事件处理程序用于检查缓存页响应的有效性。
以下示例创建一个事件处理程序 Validate,用于检查 myText TextBox Web 服务器控件的 Text 属性值。根据文本框中输入的值,Validate 返回相应的 HttpValidationStatus 枚举值。
[C#]
public void Validate(HttpContext context, Object data, ref HttpValidationStatus status)
{
if (myText.Text == "false") {
status = HttpValidationStatus.Invalid;
} else if (myText.Text == "ignore") {
status = HttpValidationStatus.IgnoreThisRequest;
} else {
status = HttpValidationStatus.Valid;
}
}
- 从一个页生存期事件中,调用 HttpCachePolicy.AddValidationCallback 方法,该操作将传递您在第 1 步的第一个参数变量中所定义的事件处理程序。
在以下代码示例中,Page_Load 方法调用具有 Validate 事件处理程序(已在第 1 步的第一个参数变量中传递)的 AddValidationCallback。
[C#]
public void Page_Load(){
Response.Cache.AddValidationCallback(new HttpCacheValidateHandler(Validate), null);
}
以下示例将第 1 步中所定义的事件处理程序用于第 2 步中的代码并将时间戳写入页中。
注意 该示例旨在简单地展示如何使缓存中的页无效。您创建的大多数方案都应该根据服务器上的某个状态(与更改的页关联)对页进行验证。
[C#]
<%@ OutputCache Duration=100 varybyparam="none" %>
<Script Language="C#" runat="server">
public void Page_Load(){
if(!IsPostback) {
myText.Text = "Enter validation request." ;
}
Response.Cache.AddValidationCallback(new HttpCacheValidateHandler(Validate), null);
stamp.InnerHtml = DateTime.Now.ToString("r");
}
public void Button1_Click(){
Validate();
}
public void Validate(HttpContext context, Object data, ref HttpValidationStatus status) {
if (myText.Text == "false") {
status = HttpValidationStatus.Invalid;
} else if (myText.Text == "ignore") {
status = HttpValidationStatus.IgnoreThisRequest;
} else {
status = HttpValidationStatus.Valid;
}
}
</Script>
<form runat="server" >
<asp:textbox runat="server" />
<br>
<asp:button click="Button1_Click" text="Click here to validate page." runat="server" />
</form>
<br>
<b>In the text box, enter false to invalidate the cached page, ignore to ignore the current request, or any other string to leave the output cached page valid. </b>
<br>
<br>
<Font size=6><B runat=server /></Font>
ASP.NET 缓存(四)--使用缓存键依赖项缓存页输出
当将页添加到输出缓存后,在超过了您在到期策略中指定的时间量之后,该页将被移除。有些时候,您要在到期之前从输出缓存中移除某个页或页的版本。例如,如果页显示易失数据(例如股票价格或温度),如果在该页到期之前数据已被更新,则该页将显示不正确的信息。
要解决该问题,ASP.NET 提供了 HttpResponse.AddCacheItemDependency 和 HttpResponse.AddCacheItemDependencies 方法,这些方法允许您缓存依赖于 Cache 对象(与该页所属的应用程序关联)中一项的页输出。
注意 通过调用 HttpResponse.RemoveOutputCacheItem 方法,可以从输出缓存中显式移除任何页。可以从 global.asax 文件,从已创建的自定义 ASP.NET 服务器控件或从页中执行该操作,具体取决于应用程序的需要。
AddCacheItemDependency 方法允许您在页和 Cache 中的单个项之间创建关系,而 AddCacheItemDependencies 方法允许您在页和 Cache 项的数组之间创建关系。当该页依赖的任何项更改或从应用程序 Cache 中移除时,都将使页输出无效并将其从输出缓存中移除。
注意 不能从 Web 窗体用户控件使用这些方法。
使缓存的页输出依赖于 Cache 项
- 以声明方式或编程方式指定缓存页输出的设置。有关更多信息,请参见设置页缓存的到期时间、设置页的可缓存性和缓存页的多个版本。
- 在页的代码声明块或代码隐藏文件中,使用 Cache.Item 属性、Cache.Add 方法或 Cache.Insert 方法将项添加到 Web 应用程序的 Cache 对象中。
- 在页的代码声明块或代码隐藏文件中,使用 Response 对象语法调用 AddCacheItemDependency 或 AddCacheItemDependencies 方法,指定该页所依赖的缓存项。
警告 若要使用这些方法,传递给它的参数必须是为 Cache.Item 属性、Cache.Add 方法或 Cache.Insert 方法中指定的缓存项所指定的缓存键。
下面的示例假定应用程序包含一个温度组件。该组件使用 Cache.Insert 方法将温度放置在应用程序 Cache 中。
[C#]
Cache.Insert("Temperature.CurrentTemperature", currentTemperature);
之后,下面的页代码(在代码声明块或代码隐藏文件中)获取存储在 Cache 中的当前温度,将其转换为字符串,然后显示它。然后,它使其输出缓存版本依赖于 Temperature.CurrentTemperature
键。从这时起,当温度组件更新温度时,便在输出缓存中刷新页版本。当随后请求该页时,该页将被重新放置在输出缓存中。
[C#]
int temperature = (int) Cache.Get("Temperature.CurrentTemperature");
LabelTemperature.Text = temperature.ToString();
Response.AddCacheItemDependency("Temperature.CurrentTemperature");
ASP.NET 缓存(五)--使用文件依赖项缓存页输出
当将页添加到输出缓存后,在超过了您在到期策略中指定的时间量之后,该页将被移除。有些时候,您要在到期之前从输出缓存中移除某个页或页的版本。若要执行该操作,可以使用 HttpResponse.AddFileDependency 方法使缓存页依赖于单个文件,或者使用 HttpResponse.AddFileDependencies 方法使缓存页依赖于 ArrayList 对象所表示的文件组。
例如,如果您使用 XML 文件作为页的数据源,则创建一个 ArrayList,它将包含页使用的所有文件的名称。然后,可以调用 AddFileDependencies 使该页依赖于该 ArrayList。当任意 XML 文件发生更改时,该页将从输出缓存中移除,并根据下一请求生成一个新页。
注意 不能从 Web 窗体用户控件使用这些方法。
注意 通过调用 HttpResponse.RemoveOutputCacheItem 方法,可以从输出缓存中显式移除任何页。可以从 global.asax 文件,从已创建的自定义 ASP.NET 服务器控件或从页中执行该操作,具体取决于应用程序的需要。
使缓存页输出依赖于一个文件
- 以声明方式或编程方式指定缓存页输出的设置。有关更多信息,请参见设置页缓存的到期时间、设置页的可缓存性和缓存页的多个版本。
- 在页的代码声明块或代码隐藏文件中,创建 String 对象。该对象将在 AddFileDependency 方法调用中作为参数变量传递。
- 在 Page_Load 方法或其他 ASP.NET 页生存期方法中,用 HttpServerUtility.MapPath 方法将第 2 步中所创建的字符串设置为依赖文件的绝对路径中。
- 在第 3 步所使用的同一页生存期方法中,访问 Response 属性语法以调用 AddFileDependency 方法,该操作将在 filename 参数中传递第 2 步所创建的 String 对象传递。
3. [C#]
4. static string filePath;
6. [C#]
7. filePath = Server.MapPath("authors.xml");
9. [C#]
10. Response.AddFileDependency(filePath);
使缓存页输出依赖于文件组
- 以声明方式或编程方式指定缓存页输出的设置。有关更多信息,请参见设置页缓存的到期时间、设置页的可缓存性和缓存页的多个版本。
- 在页的代码声明块或代码隐藏文件中,创建包含依赖文件名称的 ArrayList 对象。
- 在一个页生存期方法中(如 Page_Load),使用 Response 对象语法调用 AddFileDependencies 方法,该操作将在 filenames 参数中传递第 2 步所创建的 ArrayList 对象。
3. [C#]
4. ArrayList depAL = new ArrayList();
5. depAL.Add(Server.MapPath("authors.xml"));
6. depAL.Add(Server.MapPath("products.xml"));
8. [C#]
Response.AddFileDependencies(depAL);
以下示例使用 AddFileDependency 方法使缓存页依赖于 XML 文件 authors.xml
。一旦请求了该页,该页将在输出缓存中存储 100 秒。不过,如果在该时间到期之前,对该 XML 文件进行了更改,则该页输出将从缓存中移除。下次对该页进行请求时,输出缓存中将存储该页的新版本。若要对其进行测试,请在请求该页后,将其他项手动添加到 XML 文件中,然后从浏览器刷新该页。
[C#]
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<%@ OutputCache duration="100" varybyparam="false" %>
<html>
<script language="C#" runat="server">
static String filePath;
void Page_Load(Object Src, EventArgs E ) {
filePath = Server.MapPath("Authors.xml");
Response.AddFileDependency(filePath);
LoadData();
TimeMsg.Text = DateTime.Now.ToString("G");
}
void LoadData() {
// Read the data from the XML source.
DataSet ds = new DataSet();
FileStream fs = new FileStream(Server.MapPath("authors.xml"), FileMode.Open,FileAccess.Read);
StreamReader reader = new StreamReader(fs);
ds.ReadXml(reader);
fs.Close();
// Create a DataView object to bind to
// the DataGrid on the page.
DataView Source = new DataView(ds.Tables[0]);
// Bind the Source to the DataGrid on the page.
MyDataGrid.DataSource = Source;
MyDataGrid.DataBind();
}
</script>
<body>
<form runat="server">
<h3><font face="Verdana">File Dependencies</font></h3>
<ASP:DataGrid runat="server"
Width="300"
BackColor="#ccccff"
BorderColor="black"
ShowFooter="false"
CellPadding=3
CellSpacing="0"
Font-Name="Verdana"
Font-Size="8pt"
HeaderStyle-BackColor="#aaaadd"
/>
<p>
<i>Last/i> <asp:label runat="server" />
</form>
</body>
</html>
authors.xml
文件的内容如下所示。
<NewDataSet>
<Table>
<au_id>172-32-1176</au_id>
<au_lname>White</au_lname>
<au_fname>Johnson</au_fname>
</Table>
<Table>
<au_id>213-46-8915</au_id>
<au_lname>Green</au_lname>
<au_fname>Marjorie</au_fname>
</Table>
</NewDataSet>
ASP.NET 缓存(六)--缓存页的多个版本
根据其复杂性,当请求 ASP.NET 页时,它可能生成许多可能的响应。例如,如果您设计一个带有 HTML 窗体(该窗体允许用户查找他们家附近的零售商位置)的页,并包括城市和邮政编码输入框,则对于每个用户,页响应可能都会有所不同。您可以选择为每个城市、每个邮政编码或两者缓存页输出的版本。
ASP.NET 允许您缓存页响应的多个版本。您可以通过与请求一起传递的 GET 查询字符串或窗体 POST 参数,通过与请求一起传递的 HTTP 标头或通过发出请求的浏览器的主版本来改变输出缓存。您还可以在页中定义自定义字符串并在应用程序的 global.asax 文件中实现它影响响应缓存的方式。
ASP.NET 允许您以声明方式和编程方式来缓存页响应的多个版本,以声明方式缓存可通过在 @ OutputCache 指令上使用属性实现,以编程方式缓存可通过使用 HttpCachePolicy 类的属性和方法来实现。
明确地说,@OutputCache 指令包括三个属性允许您缓存页输出的多个版本:
- 必需的 VaryByParam 属性允许您根据 GET 查询字符串或窗体 POST 参数来改变缓存的输出。
- VaryByHeader 属性允许您根据与请求关联的 HTTP 标头来改变缓存的输出。
- VaryByCustom 属性允许您通过浏览器类型或您定义的自定义字符串来改变缓存的输出。
注意 虽然必须将 VaryByParam 属性包括在任意 @ OutputCache 指令中,但是如果不想使用它所提供的功能,您可以将其值设置为 None。
HttpCachePolicy 类提供两个属性和一个方法,它们允许您完成与上述属性相同的操作。Boolean VaryByParams 和 VaryByHeaders 属性分别允许您指定参数和标头名(您要根据参数和标头名来改变缓存)。SetVaryByCustom 方法允许您定义根据其改变输出缓存的自定义字符串。
有关这些技术的过程和深入讨论,请参见根据参数缓存页的版本、根据 HTTP 标头缓存页的版本和根据自定义字符串缓存页的版本。
ASP.NET 缓存(七)--根据参数缓存页的版本
如果您使用 GET 和 POST HTTP 方法从用户收集信息,根据用户的输入的不同,它们可以生成不同的响应。带有查询字符串的 GET 请求和 POST 请求与用来从用户收集信息的 HTML 窗体关联。根据这些参数,您可以缓存页响应的多个版本。要完成该操作,您可以使用@ OutputCache 指令的 VaryByParam 属性或 HttpCachePolicy.VaryByParams 属性。
根据查询字符串或窗体 POST 参数以声明方式缓存页输出的多个版本
- 将 @OutputCache 指令包括在您要缓存的 .aspx 文件中。一定要将必需的 Duration 属性设置为大于零的值。
- 使用 VaryByParam 属性设置根据其改变页的查询字符串或窗体 POST 参数。将下面的示例包括在 .aspx 文件的顶部会为每个到达的具有不同
City
参数值的请求缓存不同版本的页输出。
<%@ OutputCache duration="60" varybyparam="City" %>
注意 如果要通过多个参数改变输出缓存,则使用分号分隔的列表在 VaryByParam 属性中定义它们。如果要根据所有的参数值来改变缓存,请将该属性设置为星号 (*)。
根据查询字符串或窗体 POST 参数以编程方式缓存页输出的多个版本
- 在该页的代码声明块或代码隐藏类中,使用 Response.Cache 语法为已缓存的页面内容设置到期和可见性策略。您可以分别使用 HttpCachePolicy.SetExpires 和 HttpCachePolicy.SetCacheability 方法来完成此任务。
- 在相同的代码中,将参数名指定为 VaryByParams 属性的参数,并将该属性设置为 true。当具有不同
City
参数值的请求到达服务器时,下面的代码缓存页的多个版本。
3. [C#]
4. Response.Cache.VaryByParams["City"] = true;
注意 如果要通过多个参数改变输出缓存,则使用分号分隔的列表将它们包括在 VaryByParams 参数中。如果要根据所有的参数值来改变缓存,请将该属性设置为星号 (*)。
下面的示例演示根据 City
和 ZipCode
参数改变页输出。
[C#]
Response.Cache.VaryByParams["City;ZipCode"] = true;
下面的讨论详细说明如何根据具有不同值的传入请求来缓存页的版本,这些传入请求中的值是在窗体 POST 或查询字符串参数中传递的。
您的应用程序包含一个 .aspx 文件 (Mycache.aspx
),并且指定应该根据 city
参数缓存页的不同版本。到达了四个带有查询字符串的请求:两个带有 count
参数,四个带有 city
参数。
http://www.microsoft.com/caching/mycache.aspx?count=10&city=dallas
http://www.microsoft.com/caching/mycache.aspx?count=10&city=newyork
http://www.microsoft.com/caching/mycache.aspx?city=dallas
http://www.microsoft.com/caching/mycache.aspx?city=seattle
因为您指示输出缓存只根据 city
参数进行改变,所以缓存页输出的三个版本,一个用于 dallas
,一个用于 newyork
,一个用于 seattle
。第一个请求(包含 dallas
参数值)导致缓存页输出的一个版本,而第三个请求(也具有一个 dallas
参数值)从输出缓存中获得页的该版本。在这些版本保留在缓存的这段时间中,将从输出缓存满足包含 city
参数,参数值为 dallas
、new york
或 seattle
的请求。
如果要根据 city
和 count
两个参数来改变输出缓存,则缓存该页的四个版本。出现这种情况是因为第一项包含 count
查询字符串参数,而第三项却不包含。如果根据所有可能的参数改变缓存,则将为每个具有唯一参数值的请求创建输出缓存项。在当前示例中,这也是缓存页的四个版本的原因。
注意 只要页的缓存版本未到期,就将用它来满足具有相同键/值对的 GET 查询字符串或 POST 参数,而与这些参数传递的顺序无关。由于 GET 查询字符串和窗体 POST 参数区分大小写,因此如果参数值大小写不一致,则 ASP.NET 会将该参数视为与原缓存项不同,并将页的另一个版本输入输出缓存中。
ASP.NET 缓存(八)--根据 HTTP 标头缓存页的版本
@ OutputCache 指令的 VaryByHeader 属性和 HttpCachePolicy.VaryByHeaders 属性允许根据您指定的 HTTP 标头的值缓存页的多个版本。当请求页时,您可以指定传递到应用程序的单个标头、多个标头或所有标头。根据您选择的标头或标头组合,将缓存页输出的多个版本。
根据 HTTP 标头值以声明方式缓存页的版本
- 包括带有必需的 Duration 和 VaryByParam 属性的 @OutputCache 指令。必须将 Duration 属性设置为大于零的任意整数。如果不想使用 VaryByParam 属性提供的功能,请将其值设置为 None。
- 将 VaryByHeader 属性包括在 @ OutputCache 指令体中,将其值设置为要根据其改变缓存内容的 HTTP 标头的名称。下面的示例根据与 Accept-Language HTTP 标头一起传递的值设置要缓存的页的版本。
<%@ OutputCache Duration="60" VaryByParam="None" VaryByHeader="Accept-Language" %>
注意 如果要根据多个标头改变缓存的内容,则包括一个以分号分隔的标头名称的列表。如果要根据所有标头值改变缓存的内容,则将 VaryByHeader 属性设置为等于星号 (*)。
根据 HTTP 标头值以编程方式缓存页的版本
- 在该页的代码声明块或代码隐藏类中,使用 Response.Cache 语法为已缓存的页面内容设置到期和可见性策略。您可以分别使用 HttpCachePolicy.SetExpires 和 HttpCachePolicy.SetCacheability 方法来完成此任务。
- 在相同的代码中,将标头名称指定为 VaryByHeaders 属性的参数,并将属性设置为 true。当请求到达服务器时,下面的代码缓存页(其 Accept-Language HTTP 标头分配有不同的值)的多个版本。
3. [C#]
4. Response.Cache.VaryByHeaders["Accept-Language"] = true;
注意 如果要根据多个标头值改变缓存,则将 VaryByHeaders 属性参数设置为以分号分隔的有效 HTTP 标头名的列表。如果要根据所有 HTTP 标头名改变缓存中的页,请使用 VaryByUnspecifiedParameters 方法。
下面的讨论假设通过使用本主题内一个过程中的代码对页的输出进行缓存。
到达了四个对该页的请求,分别具有以下的 Accept-Language 标头。
de-lu
en-us
fr
en-us
因为第二个和第四个请求具有相同的 Accept-Language HTTP 标头值,所以只为首次请求缓存生成的响应。另外两个 Accept-Language 值生成的页输出版本也被缓存。为这四个请求总共呈现并缓存三个文档。在缓存的页到期之前,将从输出缓存满足任何对该页具有相同的 Accept-Language 值的请求。该示例演示如何根据请求浏览器的区域设置缓存全局化内容的页输出。
ASP.NET 缓存(九)--根据请求浏览器缓存页的版本
您可以使用@ OutputCache 指令的 VaryByCustom 属性或 HttpCachePolicy.SetVaryByCustom 方法根据请求该页的浏览器的主版本来改变页输出的版本。该主版本和浏览器类型信息是通过与当前请求关联的 HttpBrowserCapabilities.MajorVersion 属性传递的。您可以通过与该页关联的 Request 对象访问此信息,但是使用 ASP.NET 提供的内置功能将更简单。
根据浏览器类型以声明方式缓存页输出的多个版本
- 在 .aspx 文件中,将 @OutputCache 指令与必需的 Duration 和 VaryByParam 属性包括在一起。必须将 Duration 属性设置为大于零的任意整数。如果不想使用 VaryByParam 属性提供的功能,则必须将其值设置为 None。
- 在 @OutputCache 指令体中,包括 VaryByCustom 属性并将其设置为 browser。
<%@ OutputCache Duration="10" VaryByParam="None" VaryByCustom="browser" %>
根据自定义字符串以编程方式缓存页响应的多个版本
- 在该页的代码声明块或代码隐藏类中,使用 Response.Cache 语法为已缓存的页面内容设置到期和可见性策略。您可以分别使用 HttpCachePolicy.SetExpires 和 HttpCachePolicy.SetCacheability 方法来完成此任务。有关更多信息,请参见设置页缓存的到期时间和设置页的可缓存性。
- 在相同的代码中,在 SetVaryByCustom 方法的 custom 参数中指定 browser。
3. [C#]
4. Response.Cache.SetVaryByCustom("browser");
不管您使用哪种技术,当指定 browser 时,ASP.NET 根据在与当前请求一起传递的 Request.Browser.Type 属性中传递的浏览器名称和主版本信息来自动缓存页输出的版本。通过与该请求关联的 HttpContext 类可以使用该信息。
例如,当 Internet Explorer 5 浏览器请求页时,则将为请求的 Type 属性中传递的字符串值 "IE5" 缓存页的版本。如果是 Netscape Navigator 浏览器、Internet Explorer 的另一个版本或任何其他浏览器请求页,则将页的另一个版本添加到输出缓存中。
ASP.NET 缓存(十)--根据自定义字符串缓存页的版本
除了根据浏览器类型改变输出缓存之外,@ OutputCache 指令的 VaryByCustom 属性和 HttpCachePolicy.SetVaryByCustom 方法允许根据您定义的自定义字符串缓存页输出的多个版本。
当选择使用两种技术中的任何一种扩展输出缓存的功能时,您必须在应用程序的 Global.asax 文件中重写 HttpApplication.GetVaryByCustomString 方法。您在重写语句中编写的代码定义应用程序如何缓存根据自定义字符串或您指定的字符串改变的任何页输出。
根据自定义字符串以声明方式缓存页输出的多个版本
- 在 .aspx 文件中,将 @OutputCache 指令与必需的 Duration 和 VaryByParam 属性包括在一起。必须将 Duration 属性设置为大于零的任意整数。如果不想使用 VaryByParam 属性提供的功能,请将其值设置为 None。
- 在 @OutputCache 指令体中包括 VaryByCustom 属性,该属性设置为要根据其改变输出缓存的字符串。下面的指令根据自定义字符串“
minorversion
”改变页输出。 - 在应用程序的 global.asax 文件的代码声明块中,重写 GetVaryByCustomString 方法来为自定义字符串指定输出缓存的行为。
<%@ OutputCache Duration="10" VaryByParam="None" VaryByCustom="minorversion" %>
根据自定义字符串以编程方式缓存页输出的多个版本
- 在该页的代码声明块或代码隐藏类中,使用 Response.Cache 语法为已缓存的页面内容设置到期和可见性策略。您可以分别使用 HttpCachePolicy.SetExpires 和 HttpCachePolicy.SetCacheability 方法来完成此任务。有关更多信息,请参见设置页缓存的到期时间和设置页的可缓存性。
- 在相同的代码中,在 SetVaryByCustom 方法的 custom 参数中指定自定义字符串。以下代码将自定义字符串设置为“
minorversion
”。 - 在应用程序的 Global.asax 文件的代码声明块中,重写 GetVaryByCustomString 方法来为自定义字符串指定输出缓存的行为。
3. [C#]
4. Response.Cache.SetVaryByCustom("minorversion");
下面的示例演示一个简单的 Global.asax 文件,当应用程序中某页将自定义字符串 minorversion
传递到该文件时,该文件将重写 GetVaryByCustomString 方法。
[C#]
<script>
public override string GetVaryByCustomString(HttpContext context, string arg){
If (arg = "minorversion"){
Return "Version=" + context.Request.Browser.MinorVersion.ToString();
}
}
</script>
下面的示例是一个与前面的 Global.asax 文件交互的页,用于根据 minorversion
自定义字符串改变输出缓存。
注意 此示例页使用声明性语法来改变输出缓存。如果要以编程方式进行此操作,将类似于设置页缓存的到期时间中所显示的代码放置在 <
script>
元素的开始和结束标记之间。
[C#]
<%@ OutputCache Duration="30" VaryByParam="none" VaryByCustom="minorversion" %>
<Script language="C#" runat="server">
public void Page_Load(Object sender, EventArgs e) {
browserversion.InnerHtml = Request.Browser.MinorVersion.ToString();
timestamp.InnerHtml = DateTime.Now.ToString("r");
}
</Script>
VaryingB runat="server"/>
<BR>
AddedB runat="server" />
当以不同的值传递到 HttpBrowserCapabilities.MinorVersion 属性值来请求该示例中的页,将为发出请求的每个浏览器缓存页输出的不同版本。例如,来自 Internet Explorer 5 浏览器的请求导致缓存一个版本,而来自 Internet Explorer 5.5 浏览器的请求导致缓存另一个版本。
ASP.NET 缓存(十一)--缓存ASP.NET 页的某些部分
有时候,缓存整个页是不实际的;可能需要为每个请求动态创建页的某些部分。在这些情况下,您可能值得花时间来标识与需要大量的服务器资源来构造的页请求相关联的对象或数据。一旦标识了这些项,您就可以通过在 Web 窗体用户控件中创建这些项将它们从页的其他部分分离出来,然后在一段指定的时间中对这些项进行缓存,以节省服务器资源。这就是通常所说的片段缓存。
这项技术允许您将需要花宝贵的处理器时间来创建的页的某些部分(例如数据库查询)与页的其他部分分离开。您可以选择允许为每个请求动态生成需要较少服务器资源的页的部分。
一旦标识了要缓存的页的部分,并且创建了对这些部分中的每个部分进行封装的用户控件后,您必须确定这些用户控件的缓存策略。当在代码隐藏类中创建用户控件时,您可以使用@ OutputCache 指令以声明方式设置这些策略,或使用 PartialCachingAttribute 类以编程方式设置这些策略。
例如,如果将下面的指令包括在用户控件文件的顶部,则该控件的一个版本将在输出缓存中存储 120 秒。
<%@ OutputCache Duration="120" VaryByParam="None" %>
同样,如果使用代码隐藏开发方法开发用户控件,则将以下属性包含在类声明的元数据中时,控件版本将在输出缓存中存储 120 秒。
[C#]
[PartialCaching(120)]
[Visual Basic]
<PartialCaching(120)>
如果使用这些技术中的任何一种,则当请求包含用户控件的页时,将仅缓存用户控件。
注意 如果在页中声明并使用了为输出缓存指定的用户控件,则 ASP.NET 页分析器将根据用户控件的创建方式,对两个对象类型中的一个类型进行实例化。如果以声明方式创建用户控件,会添加 StaticPartialCachingControl 对象;如果使用 LoadControl 方法以编程方式创建用户控件,会添加 PartialCachingControl 对象。因此,当请求页时,如果页没有被缓存,分析器会将对象放入用户控件在页的控件层次结构中所占的逻辑位置。
有关可以在页输出上设置的属性的更多信息,请参见 @ OutputCache 指令的相关文档。有关如何开发用户控件的更多信息,请参见 Web 窗体用户控件。
注意 因为可以将用户控件嵌套在页上的其他服务器控件中,所以也可以嵌套已被放入输出缓存的用户控件。这意味着可以将输出缓存指令包括在输出缓存页内的用户控件中,或包括在作为另一个输出缓存用户控件一部分的用户控件中。
使用片段缓存时的常见错误
您可以在已为输出缓存指定的用户控件标记中声明 ID 属性,从而可以针对该用户控件的实例进行编程。但是,为了使代码正常工作,您必须显式验证该用户控件在输出缓存中存在。
例如,如果您以声明方式分配给某用户控件一个 ID (MyUserControl
),则可以用所包含 .aspx 文件的代码声明块中的以下代码检查该用户控件是否存在。
[C#]
void Page_Load() {
if (MyUserControl != null)
// Place code manipulating MyUserControl here.
}
[Visual Basic]
Sub Page_Load()
If MyUserControl <> Null Then
' Place code manipulating MyUserControl here.
End If
End Sub
如果编写代码来操作一个包含 @ OutputCache 指令的用户控件,则将出现错误。只为首次请求动态生成已进行输出缓存的用户控件;在指定的时间到期之前,从输出缓存满足所有后面的请求。一旦确定用户控件已经实例化,就可以以编程方式从包含的页中操作用户控件。您可以将此逻辑包括在与该用户控件关联的一个页生存期事件中,例如 Page_Load 事件或 Page_PreRender 事件中。
还应注意当具有输出缓存设置的用户控件存在于也具有输出缓存设置的 Web 窗体页时所发生的情况。如果页输出缓存存储持续时间比用户控件输出缓存存储持续时间长,则页输出缓存存储持续时间对于整个页(包括用户控件)都是有效的。例如,如果页输出缓存设置为 100 秒,而用户控件输出缓存设置为 50 秒,则整个页将在输出缓存中存储 100 秒,而与用户控件较短的时间设置无关。以下示例说明了这一点。
page01.aspx
[C#]
<%@ Page language="C#" %>
<%@ Register tagprefix="myControl" tagname="Time" src="uc01.ascx" %>
<%@ OutputCache duration="100" varybyparam="none" %>
<myControl:Time runat="server" /><br> <br> <br>
Thisp>
<% DateTime t = DateTime.Now;
Response.Write(t); %>
[Visual Basic]
<%@ Register tagprefix="myControl" tagname="Time" src="uc01.ascx" %>
<%@ OutputCache duration="100" varybyparam="none" %>
<myControl:Time runat="server" /><br> <br> <br>
Thisp>
<% Dim t As DateTime = DateTime.Now
Response.Write(t) %>
uc01.ascx
[C#]
<% @Control language="C#" %>
<% @OutputCache duration="100" varybyparam="none" %>
Thisp>
<% DateTime t = DateTime.Now;
Response.Write(t); %>
[Visual Basic]
<% @OutputCache duration="100" varybyparam="none" %>
Thisp>
<% Dim t As DateTime = DateTime.Now
Response.Write(t) %>
不过,如果页输出缓存存储持续时间比用户控件存储持续时间短,则将一直使用缓存用户输出控件,直到其存储时间到期为止,即使该页的其余部分已为某个请求重新生成。例如,如果页输出缓存设置为 50 秒,而用户控件输出缓存设置为 100 秒,则页的其余部分每到期两次,用户控件就到期一次。下面这个简单的示例说明了这一点。
page02.aspx
[C#]
<%@ Page language="C#" %>
<%@ Register tagprefix="myControl" tagname="Time" src="uc02.ascx" %>
<%@ OutputCache duration="50" varybyparam="none" %>
<myControl:Time runat="server" /><br> <br> <br>
Thisp>
<% DateTime t = DateTime.Now;
Response.Write(t); %>
uc02.ascx
[C#]
<% @Control language="C#" %>
<% @OutputCache duration="100" varybyparam="none" %>
Thisp>
<% DateTime t = DateTime.Now;
Response.Write(t); %>
ASP.NET 缓存(十二)--缓存用户控件输出的多个版本
就像可以改变已进行输出缓存的页的版本一样,您可以输出缓存具有用户控件的页的区域。通过根据控件的名称和 GET 查询字符串或窗体 POST 参数值,或只根据参数值改变用户控件输出,您可以完成该操作。通过在它所包含的 .aspx 文件中对用户控件进行多次声明,您也可以缓存页上用户控件的多个版本。您可以使用这些技术中的任何一个,不管是在 .ascx 文件中使用 @ OutputCache 指令指定用户控件的输出缓存,还是当在代码隐藏类中开发用户控件时使用 PartialCachingAttribute。
用户控件的 @ OutputCache 指令支持四个属性:VaryByParam、VaryByCustom、VaryByControl 和 Shared。PartialCachingAttribute 类包括以下四个属性:VaryByParams、VaryByControls、VaryByCustom 和 Shared,这些属性允许您通过将属性添加到代码隐瞒类的用户控件中来使用相同的技术。
当首次对包含具有输出缓存设置的用户控件的 ASP.NET 页进行请求时,控件输出的实例将保存到内存中。默认情况下,包含同一用户控件的每一页都将会在请求该页时将控件输出的另一个实例添加到内存中。
例如,如果创建了一个具有输出缓存设置的用户控件 sample.ascx,并将 sample.ascx 添加到了应用程序的 25 个 ASP.NET 页中,则输出缓存中至少会存储 25 个 sample.ascx 版本。另外,如果使用 VaryByControl、VaryByCustom 或 VaryByParam 属性修改用户控件的缓存行为,则缓存中将会有更多的用户控件输出版本。例如,假定您将 TextBox Web 服务器控件包含在用户控件中,并将其 ID 属性设置为 MyTextBox
。如果将 VaryByControl 属性设置为 MyTextBox,则对于 MyTextBox 控件接收到的每个值,都将会有一个用户控件输出版本存储在缓存中。
如果在同一应用程序的多个页中使用了相同的用户控件,则可以通过以下方法来节省内存:将用户控件 @ OutputCache 指令的 Shared 属性设置为 true,或将 PartialCachingAttribute.Shared 属性设置为 true。这意味着每个页都将访问用户控件输出的同一实例。对于经常使用和频繁缓存的用户控件,使用 Shared 属性可以节省大量的内存。
将用户控件输出添加到输出缓存中和对页输出进行相同的操作这两者存在一个主要区别。尽管两者的输出缓存都支持使用 GET 查询字符串和窗体 POST 参数创建和缓存输出的多个版本,但用户控件不支持基于 HTTP 标头的缓存。
您可以使用以下四种技术来改变输出缓存的用户控件:
- 可以使用 VaryByParam 属性或 PartialCachingAttribute.VaryByParams 属性,它们提供的功能与为页输出缓存所提供的相同。可以将这两种属性的任意一种设置为任何字符串,但需要将其等同于与所创建用户控件关联的 GET 查询字符串或格式 POST 参数。
- 可以使用 VaryByControl 属性或 PartialCachingAttribute.VaryByControls 属性,根据用户控件所包含的 ASP.NET 服务器控件 ID 来改变输出缓存用户控件。
- 可以使用 VaryByCustom 属性或 PartialCachingAttribute.VaryByCustom 属性,为改变用户控件输出所依据的自定义字符串定义代码。此方法的工作方式与改变页输出缓存的 VaryByControl 方法相同。有关更多信息,请参见根据自定义字符串缓存页版本。
- 可以在 ASP.NET 页中包含用户控件的多个实例。每个控件实例的输出都将被缓存,除非您将 @ OutputCache 指令的 Shared 属性设置为 true。