ASP.NET MVC和IE缓存 – 操作响应头无效

前端之家收集整理的这篇文章主要介绍了ASP.NET MVC和IE缓存 – 操作响应头无效前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
背景

我正在尝试帮助一位同事调试一个问题,这个问题在过去6个月内并不是一个问题。在最新部署ASP.NET MVC 2应用程序之后,强制用户打开或保存的PDF文件的FileResult响应在客户端计算机上存在足够长的时间以使PDF阅读器打开它们。

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

行为

>用户单击指向操作方法链接(具有href属性的纯超链接)。
> action方法生成一个表示为字节流的PDF。该方法总是重新创建PDF。
>在action方法中,头设置为指示浏览器如何缓存响应。他们是:

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

对于那些不熟悉headers所做的事情:

一个。缓存控制:public

Indicates that the response MAY be cached by any cache,even if it would normally be non-cacheable or cacheable only within a non- shared cache.

b。缓存控制:必须重新生效

When the must-revalidate directive is present in a response received by a cache,that cache MUST NOT use the entry after it becomes stale to respond to a
subsequent request without first revalidating it with the origin server

C。缓存控制:预检(IE5引入)

Defines an interval in seconds after which an entity must be checked for freshness. The check may happen after the user is shown the resource but ensures that on the next roundtrip the cached copy will be up-to-date.

d。缓存控制:后检(用IE5引入)

Defines an interval in seconds after which an entity must be checked for freshness prior to showing the user the resource.

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

When the no-cache directive is present in a request message,an application SHOULD forward the request toward the origin server even if it has a cached copy of what is being requested

F。到期

The Expires entity-header field gives the date/time after which the response is considered stale.

>我们从操作中返回文件

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

>向用户显示一个打开/保存对话框
>点击“保存”按预期工作,但点击“打开”启动PDF阅读器,但存储的临时文件IE已被删除,当读者尝试打开该文件时,所以它抱怨文件丢失(和它是)。

这里有六打其他应用程序使用相同的标题来强制使用Excel,CSV,PDF,Word和大量其他内容,而且从未有过问题。

问题

>标题是否正确我们正在做什么?我们希望文件临时存在(获取缓存),但始终被新版本替换,即使请求可能相同)。

在返回FileResult之前,在action方法中设置响应头。我已经要求我的同事尝试创建一个继承自FileResult的新类,而是重写ExecuteResult方法,以便它修改头,然后执行base.ExecuteResult(),而不是这样的状态。

我有一个预感,“过期”标题为“0”是罪魁祸首。根据this W3C article,将其设置为“0”意味着“已经过期”。我确实希望它过期,我只是不希望IE去除文件系统之前,应用程序处理它有机会打开它。

一如既往,谢谢!

编辑:解决方

进一步测试(使用Fiddler检查标题),我们看到我们认为设置的响应头不是浏览器解释的。自己不熟悉代码,我不知道一个根本的问题:标题在操作方法之外被踩踏。

尽管如此,我打算离开这个问题。仍然很出色的是:Expires头部的值为0与-1之间似乎有一些差异。如果有人可以通过设计来声称分歧,就IE而言,我还是想听听。至于一个解决方案,上述标头的确按照预期的方式工作,所有浏览器中的Expires值设置为-1。

更新1

帖子Making sure a web page is not cached,across all browsers详细描述了在所有浏览器中可以通过设置Expires = 0来防止缓存。我还没有在这个0 vs -1参数上出售…

解决方法

我想你应该使用
HttpContext.Current.Response.Cache.SetMaxAge (new TimeSpan (0));

要么

HttpContext.Current.Response.Headers.Set ("Cache-Control","private,max-age=0");

设置max-age = 0,这意味着高速缓存重新验证没有更多的内容(见here)。如果您在标题中另外设置ETag,并从数据中获取一些自定义的哈希校验,那么以前请求中的ETag将被发送到服务器。服务器可以返回数据,或者如果数据与以前完全一样,它可以返回空的body和HttpStatusCode.NotModified作为状态代码。在这种情况下,Web浏览器将从本地浏览器缓存中获取数据。

我建议您使用Cache-Control:private,它强制两个重要的事情:1)关闭缓存代理上的数据,有时非常积极的缓存设置2)它将允许缓存数据,但不允许共享的缓存与另一个用户。它可以解决隐私问题,因为您返回给一个用户的数据可能不被其他用户读取。默认情况下,HTTP头中的代码HttpContext.Current.Response.Cache.SetMaxAge(new TimeSpan(0))设置Cache-Control:private,max-age = 0。如果你想使用Cache-Control:public,你可以使用SetCacheability(HttpCacheability.Public);覆盖行为或使用Headers.Set而不是Cache.SetMaxAge。

如果您有兴趣研究HTTP协议的更多缓存选项,我建议您阅读caching tutorial

更新:我决定写更多的信息来清除我的立场。对应于维基百科的the information,即使像Mosaic 2.7,Netscape 2.0和Internet Explorer 3.0这样的旧网络浏览器也支持1996年3月,RFC 2068中描述的HTTP / 1.1的预标准。所以我想(但不测试)旧的网络浏览器支持max-age = 0 HTTP头。 Netscape 2.06和Internet Explorer 4.0绝对支持HTTP 1.1。

所以你应该首先问你:你使用哪些HTML标准?您是否仍然使用HTML 2.0而不是1997年1月发布的更晚的HTML 3.2?我想你至少在1997年12月使用HTML 4.0。所以如果你至少在HTML 4.0中构建你的应用程序,你的站点可以面向支持HTTP 1.1的Web客户端,并忽略(不支持)web客户端不支持HTTP 1.1。

现在关于其他“Cache-Control”标题为“private,max-age = 0”。包括标题在我看来是纯粹的偏执狂。由于我自己有一些缓存问题,所以我也尝试包括不同的其他头文件,但是后来仔细阅读RFC2616的第14.9节后,我只使用“Cache-Control:private,max-age = 0”。

可以另外讨论的唯一“缓存控制”标头是在之前引用的第14.9.4节中描述的“必须重新生效”。这是报价:

The must-revalidate directive is necessary to support reliable
operation for certain protocol features. In all circumstances an
HTTP/1.1 cache MUST obey the must-revalidate directive; in particular,
if the cache cannot reach the origin server for any reason,it MUST
generate a 504 (Gateway Timeout) response.

Servers SHOULD send the must-revalidate directive if and only if
failure to revalidate a request on the entity could result in
incorrect operation,such as a silently unexecuted financial
transaction. Recipients MUST NOT take any automated action that
violates this directive,and MUST NOT automatically provide an
unvalidated copy of the entity if revalidation fails.

Although this is
not recommended,user agents operating under severe connectivity
constraints MAY violate this directive but,if so,MUST explicitly
warn the user that an unvalidated response has been provided. The
warning MUST be provided on each unvalidated access,and SHOULD
require explicit user confirmation.

有时如果我有互联网连接的问题我看到空的页面与“网关超时”消息。它来自于“must-revalidate”指令的使用。我不认为“网关超时”消息真的帮助用户

所以,如果他们听到他的老板的电话听到“忙”信号,那么他们如何开始自我毁灭性的程序,应该在“Cache-Control”标题中另外使用“must-revalidate”指令。其他人,我建议只使用“Cache-Control:private,max-age = 0”,没有更多。

猜你在找的asp.Net相关文章