ASP.NET MVC和IE缓存-处理响应头无效

背景

我正在尝试帮助同事调试过去6个月未曾出现的问题。在最近一次部署ASP.NET MVC 2应用程序之后,FileResult迫使用户打开或保存PDF文件的响应在客户端计算机上存在的时间已经很长,以至于PDF阅读器无法打开它们。


IE的早期版本(尤其是6)是唯一受影响的浏览器。Firefox和Chrome和较新版本的IE(> 8)的行为均符合预期。考虑到这一点,下一节将定义重新创建问题所需的操作。


行为

用户单击指向动作方法的链接(带有href属性的普通超链接)。

action方法生成一个表示为字节流的PDF。该方法始终重新创建PDF。

在操作方法中,设置了标头以指示浏览器如何缓存响应。他们是:


response.AddHeader("Cache-Control", "public, must-revalidate, post-check=0, pre-check=0");

response.AddHeader("Pragma", "no-cache");

response.AddHeader("Expires", "0");

对于那些不熟悉标头功能的人:


一种。缓存控制:公共


表示该响应可以被任何缓存所缓存,即使它通常是不可缓存的或仅可在非共享缓存中缓存的。


b。缓存控制:必须重新验证


当在缓存接收到的响应中存在must-revalidate指令时,该缓存在过期之前将不能使用该条目以响应后续请求,而不必先通过原始服务器对其进行验证,则该缓存不得使用该条目


C。缓存控制:预检查(与IE5一起引入)


定义间隔(以秒为单位),在此间隔之后,必须检查实体的新鲜度。在向用户显示资源之后,可能会进行检查,但要确保在下一次往返中缓存的副本是最新的。


d。缓存控制:后检查(与IE5一起引入)


定义一个间隔(以秒为单位),在此间隔之后,必须先检查实体的新鲜度,然后才能向用户显示资源。


e。语法:无缓存(以确保与HTTP / 1.0的向后兼容性)


当请求消息中存在no-cache指令时,即使应用程序已缓存了所请求内容的副本,应用程序也应将请求转发至原始服务器


F。过期


Expires实体标题字段提供了将日期/时间视为过期的日期/时间。


我们从动作中返回文件


return File(file, "mime/type", fileName);

向用户显示一个“打开/保存”对话框


单击“保存”按预期工作,但是单击“打开”将启动PDF阅读器,但是在阅读器尝试打开文件时,已存储的IE临时文件已被删除,因此它抱怨文件丢失(并且它是)。

这里有六个其他应用程序,它们使用相同的标头将Excel,CSV,PDF,Word以及大量其他内容强加给用户,因此从来没有问题。


问题

标头是否符合我们要执行的操作?我们希望文件临时存在(被缓存),但始终将其替换为新版本,即使请求可能相同。

在返回a之前,已在action方法中设置了响应头FileResult。我已经请我的同事尝试创建一个新类,该类继承自,FileResult并改写该ExecuteResult方法,以便它修改标头,然后执行此操作base.ExecuteResult()-此状态没有状态。


我预感“ 0”的“ Expires”标头是元凶。根据W3C的这篇文章,将其设置为“ 0”意味着“已经过期”。我确实希望它过期,我只是不希望IE在处理它的应用程序有机会打开它之前,先将其从文件系统中删除。


一如既往,谢谢!


编辑:解决方案

经过进一步测试(使用Fiddler检查标头),我们看到我们认为已设置的响应标头不是浏览器正在解释的标头。我自己还不熟悉代码,但是我没有意识到一个潜在的问题:标头被踩在action方法之外。


尽管如此,我将保留这个问题。这样做仍然很出色:Expires值为0vs. 的标头之间似乎存在一些差异-1。如果有人可以通过设计声称与众不同,就IE而言,我仍然想听听。不过,对于解决方案,上述标头确实Expires可以-1在所有浏览器中使用设置为预期值的方式工作。


更新1

文章如何在所有浏览器中控制网页缓存?详细描述了可以通过设置Expires = 0来防止所有浏览器中的缓存。在此0vs -1参数上,我仍然不出售...


富国沪深
浏览 584回答 3
3回答

梵蒂冈之花

对于IE,我记得必须设置Expires: -1。 如何防止Internet Explorer中的缓存似乎通过以下代码片段进行了确认。<% Response.CacheControl = "no-cache" %><% Response.AddHeader "Pragma", "no-cache" %><% Response.Expires = -1 %>回顾代码,这就是我发现的。另外,我隐约记得,如果设置Cache-Control: private为SSL,则可能无法正确运行。Response.AddHeader("Cache-Control", "no-cache");Response.AddHeader("Expires", "-1");另外,所以,您不想缓存,是吗?提及-1,但Response.Cache改为使用方法:// Stop Caching in IEResponse.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);// Stop Caching in FirefoxResponse.Cache.SetNoStore();但是,ASP Page缓存问题(IE8)表示此代码无效。
打开App,查看更多内容
随时随地看视频慕课网APP