2012-02-23 72 views
6

有谁知道为什么如果我的页面上有cookie,输出缓存不起作用!当部署到IIS 6或7,这并不缓存,但是如果我注释掉它执行3条Response.Cookies线后面asp.net outputcache和cookies

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 

例页

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

实施例的代码。

在VS中运行时,它可以正常工作。

是否有IIS/web.config文件等一些设置,允许输出缓存,而我设置response.cookies。我知道cookie内容将被缓存,并且它只是缓存的http响应的一部分。

谢谢

Symeon。

+0

你有没有前夕r找到了解决办法? – Allov 2012-03-21 13:52:37

+1

我发现同样的事情是真实的,但没有遇到任何官方文档。明确声明它不起作用。 – JNappi 2012-04-16 16:07:21

+0

@Allov,对于延迟抱歉 - 不,我没有解决方案。除了摆脱cookie或如果我需要一个cookie,我可以在刚刚设置cookie的页面上添加脚本标记或0x0图像。 – 2012-04-17 08:50:57

回答

4

您尝试缓存此服务器端,并在同一时间,你尝试设置在客户端上的cookie - 这不是一起工作。

为什么:当你在服务器端设置页面缓存后面的代码时,缓存版本的服务没有运行(发送到客户端)。这是服务器上的缓存点。不运行任何东西,并按原样从缓存中提供。

也许你只需要在缓存头上设置缓存,而不是在服务器上缓存整个页面。

+1

我正在创建一个页面在asp.net中有一个cookie。我希望iis缓存这个页面,而不是在后面运行代码。我正在使用标准的.net代码来执行此操作。然而,它看起来像我以任何方式使用response.cookie outputcache指令破坏。这在.net中没有以任何方式记录。事实上,有一篇文章说,如果你使用缓存cookie的方式来缓存页面,我很清楚cookie是http头文件的一部分,因此将被缓存。我的问题是,如果有一个设置在iis/web.config等,使这个。它在卡西尼运行时效果不错 – 2012-02-23 11:31:01

+0

@Symeon这不符合逻辑(错误)你试图做什么。你为一个用户设置了一个cookie,那么下一个没有设置cookie的用户呢?在客户端设置的Cookie - 您已将客户端缓存与服务器缓存混合在一起。当客户端不在服务器上时,cookie也保存在缓存上 – Aristos 2012-02-23 11:46:47

+1

访问该页面的任何人都将被给予cookie,无论它是否存在。 Cookie只是http头中的文本。我明白了为什么它可能会令人困惑,但我只是认为必须有一些配置,因为它没有声明它们是互斥的,它在卡西尼中工作正常。看看这个-http://support.microsoft.com/kb/917072听起来像它应该缓存与cookie,因为他们提供了一种解决方法来阻止它。 – 2012-02-23 12:06:36

0

我有同样的问题,我通过设置位置=“ServerAndClient”和它的作品通过测试给出Aristos的场景。如果我只使用Location =“Server”,那么它不起作用。

+0

在你的情况,只有客户端(HTTP响应头缓存)将工作。如果您在响应中设置了Cookie,页面输出将不会被缓存在服务器上。 – d4n3 2012-06-06 14:39:46

1

检查,看看你正在运行的.NET 2.0 SP1,如果您已经申请MS11-100(2012年12月发布)。

我们遇到过类似的问题,最终接触到了Microsoft支持。他们证实MS11-100打破输出缓存,但声称这是设计的(由于修补程序中修复了安全漏洞的性质),目前还没有任何措施可以恢复输出缓存功能。

一个简单的测试:如果你发现你已经安装了补丁,只需卸载该补丁并重新启动即可。你应该看到输出缓存开始工作。我认为任何人都不会因为安全问题而将其推荐为生产解决方案,所以只能将其作为解决问题的手段。我们最终测试了一个更新的框架(你必须去4.0; 3.5只是2.0框架的扩展,而不是独立的框架),并且在解决所有编译错误后,输出缓存立即开始工作。

我们还致力于改变我们使用Cookie进行互动,使我们能够停留在2.0框架的方式(毕竟,它应该是更容易测试,而不是测试整个整个应用我们的cookie处理程序类)。有很多障碍,最后的产品都是“黑客”,所以这是一个不行。

2

这是由不同版本的.NET框架引起的。基本上,一些版本不会使用cookie集缓存页面。

See this blog posting

+0

欢迎来到Stack Overflow!感谢您发布您的答案!请务必仔细阅读[自助推广常见问题](http://stackoverflow.com/faq#promotion)。另请注意,每次链接到您自己的网站/产品时,您都必须*发布免责声明。 – 2012-10-05 20:57:00

-1

有可能在某些情况下工作的一种变通方法: 如果cookie不严重依赖于网页代码,但可以通过一些专门的代码来计算,您可以设置Cookie在Application_EndRequest 的Application_EndRequest的后处理OutputCache,因此缓存没有cookie存储,但是在请求被传送到客户端之前添加了设置的cookie头。

+0

我试过这个方法,收到“响应发送错误后无法修改头文件”。 – WiseGuyEh 2016-03-31 08:56:57

2

在对这个问题进行了一点研究之后,我开始了解和解决这个问题。

原因输出缓存没有发挥好与cookies

所以输出缓存将不缓存与cookies响应的原因是,一个cookie可以是用户特定的(例如身份验证,分析跟踪,等等。)。如果一个或多个cookie属性为HttpCookie.Shareable = false,则输出缓存会将响应视为不可缓存。

包括与缓存的响应

这是它获得的棘手饼干。输出缓存将响应标头和内容缓存在一起,并且在将它们发送回用户之前不提供任何钩子来修改它们。 不过,我写了下面的自定义输出缓存提供提供修改缓存响应头的能力,他们在发送之前返回给用户(要求Fasterflect NuGet包):

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(string[]), 
       typeof(int), 
       typeof(string), 
       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, object entry, DateTime utcExpiry) 
     { 
      _objectCache.Set(key, entry, 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", Flags.InstancePrivate), 
       toClone.GetFieldValue("_kernelCacheUrl", Flags.InstancePrivate), 
       toClone.GetFieldValue("_dependenciesKey", Flags.InstancePrivate), 
       toClone.GetFieldValue("_dependencies", Flags.InstancePrivate), 
       toClone.GetFieldValue("_statusCode", Flags.InstancePrivate), 
       toClone.GetFieldValue("_statusDescription", Flags.InstancePrivate), 
       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> 

而且可以使用它像这样插入饼干:

HeaderModOutputCacheProvider.RequestServedFromCache += RequestServedFromCache; 

HeaderModOutputCacheProvider.RequestServedFromCache += (sender, e) => 
{ 
    e.AddCookies(new HttpCookieCollection 
    { 
     new HttpCookie("key", "value") 
    }); 
};