6

我有一个 MVC4 GET 操作方法,它返回一个FileStreamResult. 存在仅使用 SSL 并且不允许缓存所服务文档的要求,因此它是 SSL,并且我还使用了OutputCache具有以下属性的过滤器:

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None", Location = OutputCacheLocation.None)]

这将按预期运行并生成以下响应标头:

Cache-Control: no-cache, no-store
Expires: -1
Pragma: no-cache

一切都很好,直到被要求也支持 IE8 并且这里的许多人也遇到了文件不会下载,同时没有缓存集和 SSL。IE8 及以下版本的解决方法是添加一些实际上不可行的注册表设置,或者删除违反基本要求的无缓存标头。

Cache-Control我对 Fiddler 和 IE8 进行了试验,如果我只是删除了 pragma: no-cache 标头但保持标头完好无损,则能够下载文档。这似乎没有在我的临时 Internet 文件中留下该文档的副本,但我可能需要对此进行更多测试。

考虑到这些信息,我认为使用操作上的过滤器删除编译指示可能是一项简单的任务,但似乎无论我做什么,我都无法更改OutputCache要设置的任何内容。我什至删除了该OutputCache属性并使用了:

Response.Cache.SetCacheability(HttpCacheability.NoCache)

单独使用此方法可确保我获得与以前相同的缓存设置,但它们不是在此方法调用时设置的。这只是设置了在响应管道中某个点应用的缓存策略,但我只是不知道在哪里。

有谁知道是否有一种方法可以连接到响应管道以在写入缓存标头时更改它们?

编辑IHttpModule在管道中添加了一个简单的自定义,用于查找并删除响应中的任何编译指示标头,NameValueCollection并且在设置缓存控制时编译指示不存在。这是否意味着 IIS 7.5 可能会根据它在缓存控制中看到的内容插入编译指示本身?我确定我没有为一个简单的网站设置默认值之外的任何内容。

编辑 检查Cache-Control模块中的标头值并将其设置为私有,因此缓存标头尚未应用于响应。因此,在模块执行后可能会添加缓存标头?

4

1 回答 1

1

我正在对同样的问题进行故障排除,并在删除 pragma 标头时遇到了同样的问题。当 .NET 呈现Page对象时,它会输出缓存标头。缓存处理由HttpModule. 我尝试了几种方法来删除杂注标头,但无济于事。

我还没有尝试过的一种方法看起来可能有效,但看起来像 PITA 是Response通过在输出流上实现过滤器Response.Filter = new MyCustomFilter(...)

在此之前,我尝试检查各个位置的标头,但尚未执行输出缓存处理,并且 pragma 标头不存在,因此无法删除。值得注意的是,该HttpApplication活动PreSendRequestHeaders没有奏效。

其他一些选项包括实现您自己的OutputCache模块而不是使用内置框架版本,或者以某种方式覆盖System.Web.HttpCachePolicy呈现 pragma 标头的类。

编译指示头作为HttpCacheability.NoCache选项的一部分呈现:

  if (httpCacheability == HttpCacheability.NoCache || httpCacheability == HttpCacheability.Server)
  {
    if (HttpCachePolicy.s_headerPragmaNoCache == null)
      HttpCachePolicy.s_headerPragmaNoCache = new HttpResponseHeader(4, "no-cache");
    this._headerPragma = HttpCachePolicy.s_headerPragmaNoCache;
    if (this._allowInHistory != 1)
    {
      if (HttpCachePolicy.s_headerExpiresMinus1 == null)
        HttpCachePolicy.s_headerExpiresMinus1 = new HttpResponseHeader(18, "-1");
      this._headerExpires = HttpCachePolicy.s_headerExpiresMinus1;
    }
  }

我发现的唯一实用选项是将缓存控制设置为私有,并为 URL 设置一个短的过期时间。它没有解决任何一端的根本原因,但它最终会产生几乎相同的预期效果。

于 2014-12-12T21:51:33.107 回答