ASP.NET MVC和IE缓存 - 操纵响应报头无效 [英] ASP.NET MVC and IE caching - manipulating response headers ineffective

查看:195
本文介绍了ASP.NET MVC和IE缓存 - 操纵响应报头无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图帮助同事调试已经不是问题了过去6个月的问题。最新的ASP.NET MVC 2应用程序的部署后, FileResult ,强制在用户用于打开PDF文件或保存遇到现有足够长的时间在客户端上的麻烦响应机PDF阅读器来打开它们。

I'm attempting to help a colleague debug an issue that hasn't been an issue for the past 6 months. After the most recent deployment of an ASP.NET MVC 2 application, FileResult responses that force a PDF file at the user for opening or saving are having trouble existing long enough on the client machine for the PDF reader to open them.

IE浏览器的早期版本(expecially 6)是唯一受影响的浏览器。 Firefox和Chrome和IE的新版本(> 8)所有的行为符合预期。考虑到这一点,接下来的部分定义了必要行动来重新创建问题。

Earlier versions of IE (expecially 6) are the only browsers affected. Firefox and Chrome and newer versions of IE (>8) all behave as expected. With that in mind, the next section defines the actions necessary to recreate the issue.


  1. 用户点击指向的操作方法链接(一个普通的超链接与的href 属性)。

  2. 的操作方法生成psented作为字节流的PDF重$ P $。该方法的总是的重新创建PDF文件。

  3. 在操作方法中,头被设置为指示浏览器如何缓存响应。它们是:

  1. User clicks a link that points to an action method (a plain hyperlink with an href attribute).
  2. The action method generates a PDF represented as a byte stream. The method always recreates the PDF.
  3. In the action method, headers are set to instruct browsers how to cache the response. They are:

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

对于那些不熟悉正是做的:

一个。 缓存控制:公开

表示该反应可以通过任何缓存被缓存,即使它通常会仅在一个非共享缓存不可缓存或高速缓存

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.

乙。 的Cache-Control:必重新验证

在必备revalidate指令是通过高速缓存接收到响应present,该缓存绝不能成为陈旧到一个响应后,使用入门
  后续请求没有先与原始服务器重新验证它

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

℃。 的Cache-Control:pre-检查(引入了IE5)

c. Cache-Control: pre-check (introduced with 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.

Ð。 的Cache-Control:检查后(引入了IE5)

d. Cache-Control: post-check (introduced with IE5)

定义为秒的时间间隔后一个实体必须示出该用户的资源之前,被检查的新鲜度。

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

杂注:无缓存(保证向后兼容HTTP / 1.0)

e. Pragma: no-cache (to ensure backwards compatibility with HTTP/1.0)

在无缓存指令是在请求消息present,应用程序应该转发向起源服务器的请求,即使它有被要求什么缓存副本

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);


  • 用户是一个开放psented $ P $ /保存对话框

  • The user is presented with an Open/Save dialog box

    有半打其他应用在这里,使用相同的标题,以强制Excel,CSV,PDF,Word和在用户一吨的其他内容还有从来没有一个问题。

    There are a half dozen other apps here that use the same headers to force Excel, CSV, PDF, Word, and a ton of other content at users and there's never been an issue.


    • 是正确的头什么,我们正在试图做的?我们想要的文件暂时存在(得到缓存),但总是被新版本替换,即使请求可以是相同的)。

    • Are the headers correct for what we're trying to do? We want the file to exist temporarily (get cached), but always be replaced by new versions even though the requests may be identical).

    响应报头中的操作方法设置返回前的 FileResult 。我问我的同事,试图创建一个从 FileResult 继承并代替覆盖的ExecuteReuslt 方法,这样一个新的类它修改标题,然后执行 base.ExecuteResult()代替 - 对无状态

    The response headers are set in the action method before return a FileResult. I've asked my colleague to try creating a new class that inherits from FileResult and to instead override the ExecuteResult method so that it modifies the headers and then does base.ExecuteResult() instead -- no status on that.

    我有一种预感的过期的0的标题是罪魁祸首。根据这个W3C文章,将其设置为0意味着已经过期。我不希望它是过期的,我只是不想IE去应用程序之前删除它关闭文件系统处理它得到一个机会来打开它。

    I have a hunch the "Expires" header of "0" is the culprit. According to this W3C article, setting it to "0" implies "already expired." I do want it to be expired, I just don't want IE to go removing it off of the filesystem before the application handling it gets a chance to open it.

    一如往常,谢谢!

    在进一步的测试(使用Fiddler检查头),我们看到,我们以为是越来越设置响应标头是不是那些被浏览器PTED间$ P $。已经不熟悉了code我自己,我不知道一个基本的问题:头都拿到的操作方法外跺着脚

    Upon further testing (using Fiddler to inspect the headers), we were seeing that the response headers we thought were getting set were not the ones being interpreted by the browser. Having not been familiar with the code myself, I was unaware of an underlying issue: the headers were getting stomped on outside of the action method.

    不过,我要离开这个问题的公开。依然突出是这样的:有似乎是过期 0 的主场迎战头值<$有出入C $ C> 1 。如果以不同的在设计上,在关于IE 的任何人都可以宣称,我还是想听到它。作为一个解决方案,虽然,上面的标题做工作按预期在所有浏览器设置为 1 过期价值

    Nonetheless, I'm going to leave this question open. Still outstanding is this: there seems to be some discrepancy between the Expires header having a value of 0 vs. -1. If anybody can lay claim to differences by design, in regards to IE, I would still like to hear about it. As for a solution though, the above headers do work as intended with the Expires value set to -1 in all browsers.

    该职位确保网页不被缓存,跨详细的缓存可以$ P描述所有的浏览器$在所有浏览器pvented与设置的帮助过期= 0,我还没有对这个出售 0 VS 1 参数...

    The post Making sure a web page is not cached, across all browsers describes in detail that caching can be prevented in all browsers with the help of setting Expires = 0. I'm still not sold on this 0 vs -1 argument...

    推荐答案

    我觉得你应该只使用

    HttpContext.Current.Response.Cache.SetMaxAge (new TimeSpan (0));
    

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

    设置最大年龄= 0 这意味着没有更多的缓存重新验证(见的这里)。如果你将与来自数据散列的一些自定义的校验头另行的ETag 设置,从previous请求的ETag将被发送到服务器。服务器能够要么返回数据,或在情况下的数据是完全和以前一样,它可以返回空的身体和的HTTPStatus code.NotModified 作为状态code。在这种情况下Web浏览器将从本地浏览器缓存中获取数据。

    to set max-age=0 which means nothing more as the cache re-validating (see here). If you would be set additionally ETag in the header with some your custom checksum of hash from the data, the ETag from the previous request will be sent to the server. The server are able either to return the data or, in case that the data are exactly the same as before, it can return empty body and HttpStatusCode.NotModified as the status code. In the case the web browser will get the data from the local browser cache.

    我建议你使用缓存控制:私人迫使两个重要的事情:1)关闭缓存的代理,这有时非常积极的缓存设置数据2)它会允许的数据的高速缓存,而不是允许与另一个用户缓存的共享。它可以解决隐私问题,因为您返回到一个用户的数据都将不可被其他用户读取。顺便code HttpContext.Current.Response.Cache.SetMaxAge(新的TimeSpan(0))设置缓存控制:私人的,最大年龄= 0 默认情况下的HTTP标头。如果你想使用缓存控制:公开您可以使用 SetCacheability(HttpCacheability.Public); 来覆盖行为或使用 Headers.Set 而不是 Cache.SetMaxAge

    I recommend you to use Cache-Control: private which force two important things: 1) switch off caching the data on the proxy, which has sometimes very aggressive caching settings 2) it will allows the caching of the the data, but not permit sharing of the cache with another users. It can solve privacy problems because the data which you return to one user could be not allowed to read by another users. By the way the code HttpContext.Current.Response.Cache.SetMaxAge (new TimeSpan (0)) set Cache-Control: private, max-age=0 in the HTTP header by default. If you do want to use Cache-Control: public you can use SetCacheability (HttpCacheability.Public); to overwrite the behavior or use Headers.Set instead of Cache.SetMaxAge.

    如果您有兴趣学习HTTP协议的更多的缓存选项,我建议您阅读缓存教程

    If you have interest to study more caching options of HTTP protocol I would recommend you to read the caching tutorial.

    更新时间::我决定写一些更多的信息,清楚我的立场。对应于的信息来自于维基百科即便如此旧的Web浏览器,如马赛克2.7 的版本,Netscape 2.0和Internet Explorer 3.0支持三月1996年,$ p $ HTTP的p-标准/ 1.1 RFC 2068中描述,所以我想(而不是测试),旧的浏览器都支持最大年龄= 0 HTTP标头。以任何方式的Netscape 2.06和Internet Explorer 4.0明确支持HTTP 1.1。

    UPDATED: I decide to write some more information to clear my position. Corresponds to the information from the Wikipedia even so old web browsers like Mosaic 2.7, Netscape 2.0 and Internet Explorer 3.0 supports March 1996, pre-standard of HTTP/1.1 described in RFC 2068. So I suppose (but not test it) that the old web browsers support max-age=0 HTTP header. In any way Netscape 2.06 and Internet Explorer 4.0 definitively supports HTTP 1.1.

    所以,你应该先问问你:你使用的HTML标准?你还在用HTML 2.0,而不是更晚HTML 3.2刊登在1997年1月?我想你至少使用刊登在1997年12月所以,如果你至少在HTML 4.0构建应用程序,您的网站可以在Web客户导向,支持HTTP 1.1,而忽略HTML 4.0(不支持)的Web客户端这不支持HTTP 1.1。

    So you should ask you first: which HTML standards you use? Do you still use HTML 2.0 instead of more late HTML 3.2 published in January 1997? I suppose you use at least HTML 4.0 published in December 1997. So if you build your application at least in HTML 4.0, your site can be oriented on the web clients which supports HTTP 1.1 and ignore (don't support) the web clients which don't support HTTP 1.1.

    现在关于其他缓存控制头为私人,最大年龄= 0。包括头在我看来是的纯偏执。由于我有一些问题,缓存我自己也试过,包括不同的其它头,但仔细阅读RFC2616的14.9节后来经过我只用缓存控制:私人,最大年龄= 0。

    Now about other "Cache-Control" headers as "private, max-age=0". Including of the headers is in my opinion is pure paranoia. As I have some caching problem myself I tried also to include different other headers, but later after reading carefully the section 14.9 of RFC2616 I use only "Cache-Control: private, max-age=0".

    唯一的缓存控制,它可以另外讨论的标头是必须重新验证关于这一点我之前提到的14.9.4节描述。这里是报价:

    The only "Cache-Control" header which can be additionally discussed is "must-revalidate" described on the section 14.9.4 which I referenced before. Here is the quote:

    的必备revalidate指令是必要的支持可靠
      对于某些协议功能的操作。在任何情况下的
      HTTP / 1.1缓存必须服从必备revalidate指令;尤其是,
      如果缓存不能以任何理由到原服务器,它必须
      产生一个504(网关超时)响应。

    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.

    服务器应该发送的必revalidate指令当且仅当
      未能重新验证的实体可能会导致一个请求
      不正确的操作,诸如默默地未执行金融
      交易。收件人必须没有采取任何自动操作的
      违反该指令,不得将自动提供
      实体的未经验证的副本,如果再验证失败。

    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.

    有时候,如果我有互联网连接我看到了空白页以网关超时消息的问题。它来自必须重新验证指令的用法。我不认为网关超时消息,真正帮助用户。

    Sometime if I have problem with Internet connection I see the empty page with "Gateway Timeout" message. It come from the the usage of "must-revalidate" directive. I don't think that "Gateway Timeout" message really help the user.

    于是人,preFER如何,如果他听到在电话会议上向他的老板忙的信号开始自我毁灭的过程中,应另外使用必须重新验证指令中的缓存控制头。我建议其他人只是用缓存控制:私人,最大年龄= 0,仅此而已。

    So the persons, how prefer to start self-destructive procedure if he hears "Busy" signal on the call to his boss, should additionally use "must-revalidate" directive in the "Cache-Control" header. Other persons I recommend just use "Cache-Control: private, max-age=0" and nothing more.

    这篇关于ASP.NET MVC和IE缓存 - 操纵响应报头无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆