ASP.NET OutputCache和Cookies
有谁知道为什么如果我的页面上有cookie,输出缓存不起作用!
示例页面 <%@ Page Language="VB" AutoEventWireup="false" CodeFile="ct.aspx.vb" Inherits="ct" %> <%@ OutputCache Duration="600" Location="Server" VaryByParam="none" %> <!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></title> </head> <body> <form id="form1" runat="server"> <div> <h1>Cache test</h1> <p id="rndout" runat="server"></p> </div> </form> </body> </html> 后面的示例代码: Partial Class ct Inherits System.Web.UI.Page Protected Sub Page_Load(sender As Object,e As System.EventArgs) Handles Me.Load Dim rc As New Random() Dim rn As Integer rn = rc.Next() rndout.InnerHtml = rn.ToString Response.Cookies("sym")("hello") = "world" Response.Cookies("sym").Expires = DateTime.Now.AddDays(370) Response.Cookies("sym").Domain = Application.Get("cookieurl") End Sub End Class 当部署到iis 6或7时,这不会缓存,但是如果我注释掉它的3个Response.Cookies行. 在VS中运行时,它可以正常工作. 在我设置response.cookies时,iis / web.config等中是否有一些设置允许outputcache.我理解cookie内容将被缓存,它只是缓存的http响应的一部分. 解决方法
在对这个问题进行了一些研究之后,我逐渐理解并解决了这个问题.
输出缓存与cookie不兼容的原因 因此,输出缓存不会使用cookie缓存响应的原因是cookie可能是特定于用户的(例如,身份验证,分析跟踪等).如果一个或多个具有属性HttpCookie.Shareable = false的cookie,则输出缓存会认为响应不可缓存. 包含带缓存响应的cookie 这是它变得棘手的地方.输出缓存将响应头和内容缓存在一起,并且在将它们发送回用户之前不提供任何钩子来修改它们. using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Caching; using System.Web; using System.Web.Caching; using Fasterflect; namespace CustomOutputCache { /// <summary> /// An output cache provider that has ability to modify the http header collection before a cached response is served back to the user. /// </summary> public class HeaderModOutputCacheProvider : OutputCacheProvider { private static readonly Type OutputCacheEntryType,HttpCachePolicySettingsType; private static readonly Type[] ParameterTypes; public static event EventHandler<CachedRequestEventArgs> RequestServedFromCache; static HeaderModOutputCacheProvider() { var systemWeb = typeof(HttpContext).Assembly; OutputCacheEntryType = systemWeb.GetType("System.Web.Caching.OutputCacheEntry"); HttpCachePolicySettingsType = systemWeb.GetType("System.Web.HttpCachePolicySettings"); ParameterTypes = new[]{ typeof(Guid),HttpCachePolicySettingsType,typeof(string),typeof(string[]),typeof(int),typeof(List<HeaderElement>),typeof(List<ResponseElement>) }; } private readonly ObjectCache _objectCache; public HeaderModOutputCacheProvider() { _objectCache = new MemoryCache("output-cache"); } #region OutputCacheProvider implementation public override object Get(string key) { var cachedValue = _objectCache.Get(key); if (cachedValue == null) return null; if (cachedValue.GetType() != OutputCacheEntryType) return cachedValue; var cloned = CloneOutputCacheEntry(cachedValue); if (RequestServedFromCache != null) { var args = new CachedRequestEventArgs(cloned.HeaderElements); RequestServedFromCache(this,args); } return cloned; } public override object Add(string key,object entry,DateTime utcExpiry) { _objectCache.Set(key,entry,new CacheItemPolicy { AbsoluteExpiration = utcExpiry }); return entry; } public override void Set(string key,new CacheItemPolicy { AbsoluteExpiration = utcExpiry }); } public override void Remove(string key) { _objectCache.Remove(key); } #endregion private IOutputCacheEntry CloneOutputCacheEntry(object toClone) { var parameterValues = new[] { toClone.GetFieldValue("_cachedVaryId",Flags.InstancePrivate),toClone.GetFieldValue("_settings",toClone.GetFieldValue("_kernelCacheUrl",toClone.GetFieldValue("_dependenciesKey",toClone.GetFieldValue("_dependencies",toClone.GetFieldValue("_statusCode",toClone.GetFieldValue("_statusDescription",CloneHeaders((List<HeaderElement>)toClone.GetFieldValue("_headerElements",Flags.InstancePrivate)),toClone.GetFieldValue("_responseElements",Flags.InstancePrivate) }; return (IOutputCacheEntry)OutputCacheEntryType.CreateInstance( parameterTypes: ParameterTypes,parameters: parameterValues ); } private List<HeaderElement> CloneHeaders(List<HeaderElement> toClone) { return new List<HeaderElement>(toClone); } } public class CachedRequestEventArgs : EventArgs { public CachedRequestEventArgs(List<HeaderElement> headers) { Headers = headers; } public List<HeaderElement> Headers { get; private set; } public void AddCookies(HttpCookieCollection cookies) { foreach (var cookie in cookies.AllKeys.Select(c => cookies[c])) { //more reflection unpleasantness :( var header = cookie.CallMethod("GetSetCookieHeader",Flags.InstanceAnyVisibility,HttpContext.Current); Headers.Add(new HeaderElement((string)header.GetPropertyValue("Name"),(string)header.GetPropertyValue("Value"))); } } } } 你会像这样连线: <system.web> <caching> <outputCache defaultProvider="HeaderModOutputCacheProvider"> <providers> <add name="HeaderModOutputCacheProvider" type="CustomOutputCache.HeaderModOutputCacheProvider"/> </providers> </outputCache> </caching> </system.web> 并且可以像这样使用它来插入cookie: HeaderModOutputCacheProvider.RequestServedFromCache += RequestServedFromCache; HeaderModOutputCacheProvider.RequestServedFromCache += (sender,e) => { e.AddCookies(new HttpCookieCollection { new HttpCookie("key","value") }); }; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp-classic – 经典ASP:RecordSet字段没有任何价值
- asp.net – 确保dot.net站点始终运行
- asp.net – 如果我只是在做一个查找表,我应该使用自动生成的
- asp.net – jqgrid editurl:控制器动作参数
- asp.net-mvc-3 – MVC3,多文件上传,模型绑定
- asp.net – 如何将最新的TFS变更集编号插入到aspx页面?
- 比较自托管:WCF与HttpListener
- asp.net ajax实现无刷新验证码
- 为什么在手动刷新响应时ASP.NET将使用Transfer-Encoding头替
- asp.net – Sitecore:Sitecore.Web.WebUtil.Redirect对Res
- ASP.NET MVC 3 Gotcha(Bug?):GET和POST的不同参
- .net – 如何动态清除用户控件中的所有控件?
- asp.net-mvc-4 – 在umbraco中获取错误无法找到类
- asp.net-mvc – Elmah日志文件删除,手动还是有设
- asp.net-mvc – 在ASP.Net MVC中寻找转发器类型功
- ASP.NET Page_Init被解雇了两次!
- asp.net-mvc – 我真的需要一个ORM吗?
- asp.net-core – 重新挑战ASP.NET Core中经过身份
- asp.net-mvc – Route Id覆盖Model.Id
- asp.net – 在开发,分段和生产环境之间区分web.c