IIS7.5 max-age issue(asp.net mvc output cache) - asp.net-mvc

We use Windows server 2008 R2 Enterprise And IIS7.5.7600.16385,
and i deployed a simple web (asp.net mvc, c#, .net framework 4.5.1) on the server.
a controller like below, and *.cshtml only output a datetime:
public class DetailController : Controller
{
[OutputCache(Duration = 300, VaryByParam = "id")]
public ActionResult Index(int id)
{
return View();
}
}
when i first request the url http://localhost:80/Detail/Index?id=3 , the response is correct:
Cache-Control:public, max-age=300
Date:Mon, 24 Oct 2016 12:11:59 GMT
Expires:Mon, 24 Oct 2016 12:16:51 GMT
Last-Modified:Mon, 24 Oct 2016 12:11:51 GMT
but, when i request the url again(ctrl+f5), the max-age incorrect (then the response is from the server cache):
Cache-Control:public, max-age=63612908450
Date:Mon, 24 Oct 2016 12:16:34 GMT
Expires:Mon, 24 Oct 2016 12:20:50 GMT
Last-Modified:Mon, 24 Oct 2016 12:15:50 GMT
i don't know why the max-age so large, and how it generated, it will reconvert when the output cache expired (ctrl+f5).
In my production env, the incorrect max-age cause a url link click read the content from browser's disk cache.
any one know how and how to fixed it?

This is a known issue and a bug is open for .NET 4.6.2 coming with KB151864.
Please see here for additional details: https://github.com/Microsoft/dotnet/issues/330
This is going to be fixed in .NET 4.6.3. I currently don't know if a fix will be made available earlier for 4.6.2.
The only known workaround at present is to downgrade and remove KB151864, when possible.
NOTE: the bug is affecting ONLY the compilation of the "max-age" attribute in the Cache-Control header for the cached responses. The actual caching mechanism and lifetime expiration is working.

I just spoke with Microsoft Support team and this is what they responded me:
The suggested workaround is to downgrade the frame work from 4.6.2 to
4.6.1 by uninstalling the update KB31511864.
Go to control panel -> programs -> Programs and Feature -> Installed Updates.
And remove KB3151864, that will fix this issue.

Related

mochiweb: disable headers ordering

I checked mochiweb response headers, and they are always ordered (descending):
< Server: MochiWeb/1.0 (Any of you quaids got a smint?)
< last-modified: Sun, 30 Aug 2015 23:13:04 GMT
< Date: Sun, 30 Aug 2015 23:15:15 GMT
< Content-Type: text/html
< Content-Length: 89
This looks to be because of mochiweb headers are being handled with an erlang gb_tree, which is later converted to a list so it comes ordered.
Is there a way to change this? as this could resolve in problems (sometimes) like here and here
My problem is that I am trying to create a service that replicates some requests and I am using mochiweb for this, but Headers are being ordered so it isn't completely replicating the response correctly.
Fixed here:
mochiweb commit 952087e
It was a problem with formatting the headers in the response, and not in mochiweb_headers.

Firefox stored cached incomplete response

I just found a partial response being cached as complete in one of our customer's machines, which rendered the whole website unusable. And I have absolutely no idea, what could possible have gone wrong there.
So what could have possibly gone wrong in the following setup?
On the server-side, we have an ASP.NET-application running. One IHttpHandler handles requests to javascript-files. It basically minifies the files as they are requested and writes the result on the response-stream. It does also log the length of the string being written to the Response-Stream:
String javascript = /* Javascript is retrieved here */;
HttpResponse response = context.Response;
response.ContentEncoding = Encoding.UTF8;
response.ContentType = "application/javascript";
HttpCachePolicy cache = response.Cache;
cache.SetCacheability(HttpCacheability.Public);
cache.SetMaxAge(TimeSpan.FromDays(300));
cache.SetETag(ETag);
cache.SetExpires(DateTime.Now.AddDays(300));
cache.SetLastModified(LastModified);
cache.SetRevalidation(HttpCacheRevalidation.None);
response.Headers.Add("Vary", "Accept-Encoding");
Log.Info("{0} characters sent", javascript.length);
response.Write(javascript);
response.Flush();
response.End();
The content is then normally sent using gzip-encoding with chunked transfer-encoding. Seems simple enough to me.
Unfortunately, I just had a remote-session with a user, where only about 1/3 of the file was in the cache, which broke the file of course (15k instead of 44k). In the cache, the content-encoding was also set to gzip, all communication took place via https.
After having opened the source-file on the user's machine, I just hit Ctrl-F5 and the full content was displayed immediately.
What could have possibly gone wrong?
In case it matters, please find the cache-entry from Firefox below:
Cache entry information
key: <resource-url>
fetch count: 49
last fetched: 2015-04-28 15:31:35
last modified: 2015-04-27 15:29:13
expires: 2016-02-09 14:27:05
Data size: 15998 B
Security: This is a secure document.
security-info: (...)
request-method: GET
request-Accept-Encoding: gzip, deflate
response-head: HTTP/1.1 200 OK
Cache-Control: public, max-age=25920000
Content-Type: application/javascript; charset=utf-8
Content-Encoding: gzip
Expires: Tue, 09 Feb 2016 14:27:12 GMT
Last-Modified: Tue, 02 Jan 2001 11:00:00 GMT
Etag: W/"0"
Vary: Accept-Encoding
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
Date: Wed, 15 Apr 2015 13:27:12 GMT
necko:classified: 1
Your clients browser is most likely caching the JavaScript files which would mean the src of your scripts isn't changing.
For instance if you were to request myScripts
<script src="/myScripts.js">
Then the first time, the client would request that file and any further times the browser would read its cache.
You need to append some sort of unique value such as a timestamp to the end of your scripts so even if the browser caches the file, the new timestamp will act like a new file name.
The client receives the new scripts after pressing Ctrl+F5 because this is a shortcut to empty the browsers cache.
MVC has a really nice way of doing this which involves appending a unique code which changes everytime the application or it's app pool is restarted. Check out MVC Bundling and Minification.
Hope this helps!

Get server data in Delphi 2010

I have a problem I'm trying to use the component idhttp using indy in delphi 2010, the problem is I'm trying to get the following information when using idHTTP1.Head ():
HTTP/1.1 200 OK
Date: Mon, 16 Jun 2003 2:53:29 GMT
Server: Apache/1.3.3 (Unix) (Red Hat / Linux)
Last-Modified: Wed, October 7, 1998 11:18:14 GMT
ETag: "1813-49b-361b4df6"
Accept-Ranges: bytes
Content-Length: 1179
Connection: close
Content-Type: text / html
The problem is not that I have to do to get this information because I can not get with idHTTP1.Request.RawHeaders.Values​​, someone could say that I have to do.
You are looking in the wrong place. You need to look in IdHTTP1.**Response**.RawHeaders instead. Also, all of those values actually have individual properties associated with them, eg:
IdHTTP1.Response.ResponseVersion
IdHTTP1.Response.ResponseCode
IdHTTP1.Response.ResponseText
IdHTTP1.Response.Date
IdHTTP1.Response.Server
IdHTTP1.Response.LastModified
IdHTTP1.Response.ETag
IdHTTP1.Response.AcceptRanges
IdHTTP1.Response.ContentLength (also IdHTTP1.Response.HasContentLength)
IdHTTP1.Response.Connection
IdHTTP1.Response.ContentType

Orbeon cache headers

I'm running orbeon 3.70beta and I need to avoid cache. In particular I need orbeon to return in the http response the following attributes:
Cache-Control=max-age=0
Pragma=no-cache
Expires=0
I tried this properties on the properties.xml :
<property as="xs:string"
name="oxf.http.page.cache-headers"
value="Cache-Control: max-age=0; Pragma: no-cache; Expires: 0"/>
<property as="xs:string"
name="oxf.http.resource.cache-headers"
value="Cache-Control: max-age=0; Pragma: no-cache; Expires: 0"/>
But I'm still getting a response like this:
Cache-Control:public
Content-Language:en-US
Content-Length:772
Content-Type:text/html; charset=utf-8
Date:Fri, 20 Jul 2012 13:14:18 GMT
Expires:Fri, 20 Jul 2012 13:14:18 GMT
Last-Modified:Fri, 20 Jul 2012 13:00:51 GMT
Pragma:
Server:WebSphere Application Server/6.1
Note:
Also I add a filter in the web.xml and add the compiled filter but it
seems that orbeon is overriding the cache headers in some point.
Note2:
I already override the cache headers on other application (using a filter) in the
same websphere and the headers are successfully overridden. So the Websphere
is not the problem.
I will appreciate the help very much.
Thanks,
Francisco.
These properties were added for Orbeon Forms 4.0 so they won't work with 3.7. (3.7.1 is more than 3 years old, and the 3.7.0beta build you are using is probably even older.) Your best bet is to do this by using a servlet filter like UrlRewriteFilter or a front-end HTTP server like Apache.

Why does Chrome use the client cache differently in these two scenarios?

I'm working on a small single-page application using HTML5. One feature is to show PDF documents embedded in the page, which documents can be selected form a list.
NOw I'm trying to make Chrome (at first, and then all the other modern browsers) use the local client cache to fulfill simple GET request for PDF documents without going through the server (other than the first time of course). I cause the PDF file to be requested by setting the "data" property on an <object> element in HTML.
I have found a working example for XMLHttpRequest (not <object>). If you use Chrome's developer tools (Network tab) you can see that the first request goes to the server, and results in a response with these headers:
Cache-Control:public,Public
Content-Encoding:gzip
Content-Length:130
Content-Type:text/plain; charset=utf-8
Date:Tue, 03 Jul 2012 20:34:15 GMT
Expires:Tue, 03 Jul 2012 20:35:15 GMT
Last-Modified:Tue, 03 Jul 2012 20:34:15 GMT
Server:Microsoft-IIS/7.5
Vary:Accept-Encoding
The second request is served from the local cache without any server roundtrip, which is what I want.
Back in my own application, I then used ASP-NET MVC 4 and set
[OutputCache(Duration=60)]
on my controller. The first request to this controller - with URL http://localhost:63035/?doi=10.1155/2007/98732 results in the following headers:
Cache-Control:public, max-age=60, s-maxage=0
Content-Length:238727
Content-Type:application/pdf
Date:Tue, 03 Jul 2012 20:45:08 GMT
Expires:Tue, 03 Jul 2012 20:46:06 GMT
Last-Modified:Tue, 03 Jul 2012 20:45:06 GMT
Server:Microsoft-IIS/8.0
Vary:*
The second request results in another roundtrip to the server, with a much quicker response (suggesting server-side caching?) but returns 200 OK and these headers:
Cache-Control:public, max-age=53, s-maxage=0
Content-Length:238727
Content-Type:application/pdf
Date:Tue, 03 Jul 2012 20:45:13 GMT
Expires:Tue, 03 Jul 2012 20:46:06 GMT
Last-Modified:Tue, 03 Jul 2012 20:45:06 GMT
Server:Microsoft-IIS/8.0
Vary:*
The third request for the same URL results in yet another roundtrip and a 304 response with these headers:
Cache-Control:public, max-age=33, s-maxage=0
Date:Tue, 03 Jul 2012 20:45:33 GMT
Expires:Tue, 03 Jul 2012 20:46:06 GMT
Last-Modified:Tue, 03 Jul 2012 20:45:06 GMT
Server:Microsoft-IIS/8.0
Vary:*
My question is, how should I set the OutputCache attribute in order to get the desired behaviour (i.e. PDF requests fullfilled from the client cache, within X seconds of the initial request)?
Or, am I not doing things right when I cause the PDF to display by setting the "data" property on an <object> element?
Clients are never obligated to cache. Each browser is free to use its own heuristic to decide whether it is worth caching an object. After all, any use of cache "competes" with other uses of the cache.
Caching is not designed to guarantee a quick response; it is designed to, on average, increase the likelihood that frequently used resources that are not changing will already be there. What you are trying to do, is not what caches are designed to help with.
Based on the results you report, the version of Chrome you were using in 2012 decided it was pointless to cache an object that would expire in 60 seconds, and had only been asked for once. So it threw away the first copy, after using it. Then you asked a second time, and it started to give this URL a bit more priority -- it must have remembered recent URLs, and observed that this was a second request -- it kept the copy in cache, but when the third request came, asked server to verify that it was still valid (presumably because the expiration time was only a few seconds away). The server said "304 -- not modified -- use the copy you cached". It did NOT send the pdf again.
IMHO, that was reasonable cache behavior, for an object that will expire soon.
If you want to increase the chance that the PDF will stick around longer, then give a later expiration time, but say that it must check with the server to see if it is still valid.
If using HTTP Cache-Control header, this might be: private, max-age: 3600, must-revalidate. With this, you should see a round-trip to server, which will give 304 response as long as the page is valid. This should be a quick response, since no data is sent back -- the browser's cached version is used.
private is optional -- not related to this caching behavior -- I'm assuming whatever this volatile PDF is, it only makes sense for the given user and/or shouldn't be hanging around for a long time, in some shared location.
If you really need the performance of not talking to the server at all, then consider writing javascript to hide/show the DOM element holding that PDF, rather than dropping it, and needing to ask for it again.
Your javascript code for the page is the only place that "understands" that you really want that PDF to stick around, even if you aren't currently showing it to the user.
Have you tried setting the Location property of the OutputCache to "Client"
[OutputCache(Duration=60, Location = OutputCacheLocation.Client)]
By default the location property is set to "Any" which could mean that the response is cached on the client, on a proxy, or at the server.
more at MSDN OutputCacheLocation

Resources