I'm trying to get YSlow to give me an A on the "Add Expires header" section by setting the web.config file.
I've been looking around and this is what I put in based on what's out there:
<staticContent>
<clientCache httpExpires="15.00:00:00" cacheControlMode="UseExpires"/>
</staticContent>
</system.webServer>
This is what I'm seeing in Firebug:
Response Headers
HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Sun, 28 Aug 2011 13:54:50 GMT
X-AspNet-Version: 4.0.30319
Cache-Control: private
Content-Type: image/jpeg
Content-Length: 24255
Connection: Close
Request Headersview source
Host localhost:50715
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0
Accept image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip, deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection keep-alive
Referer http://localhost:50715/MySite/SiteHome.html
Pragma no-cache
Cache-Control no-cache
However, when I look at it in Firefox, Yslow is still giving an F on this, even after a Crtl-F5
What am I missing?
Thanks.
From .NET Daily, I successfully applied this to a PHP site on IIS. It sets the max age to 30 days from now, rather than having to specify an explicit date.
Add this to your web.config file:
<system.webServer>
<staticContent>
<clientCache cacheControlMaxAge="30.00:00:00" cacheControlMode="UseMaxAge"/>
</staticContent>
</system.webServer>
This configuration satisfies both PageSpeed "Leverage browser caching" and YSlow "Add Expires headers". YSlow requires a value greater than 7 days. PageSpeed requires between 30 days and 1 year.
From the clientCache documentation
The value for the httpExpires attribute must be a fully-formatted date and time that follows the specification in RFC 1123. For example:
Fri, 01 Jan 2010 12:00:00 GMT
So, if you want to use the http expires headers for your static content, set it like this:
<staticContent>
<clientCache cacheControlMode="UseExpires" httpExpires="Sun, 1 Jan 2017 00:00:00 UTC" />
</staticContent>
Update (to above comments): This will most probably still not work in the built in VS server. I'm not sure if it supports expires headers at all. AFAIK this is an IIS setting.
I believe the recommendation is to add expires on static content rather than ASPX pages. Make sure you are checking the request headers for static content such as images and not the ASPX file.
Check out :
http://developer.yahoo.com/performance/rules.html
Related
When CORS is configured (and seemingly working) it still returns a 405 for the OPTIONS verb.
CORS is configured via the Owin NuGet package, Microsoft.Owin.Cors and it seems to return the correct headers.
I notice the issue in Fiddler when I fake a preflight OPTIONS request. The headers come back properly when I propose that I am calling from an allowed domain and they are correctly absent if I propose some other domain - its working.
But why the 405?
HTTP/1.1 405 Method Not Allowed
Cache-Control: no-cache
Pragma: no-cache
Allow: GET,PUT,DELETE
Content-Type: application/xml; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
Access-Control-Allow-Origin: http://localhost:12345
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 01 Oct 2015 18:59:32 GMT
Content-Length: 96
<Error><Message>The requested resource does not support http method 'OPTIONS'.</Message></Error>
Note the Access-Control-Allow-Origin is present, so I guess the browser will be okay, or will the browser be 'put off' by the negative 405?
I think you may check first allowed verb's setting on the configurations of IIS.
refer to http://www.iis.net/configreference/system.webserver/security/requestfiltering/verbs
web.config example
<configuration>
<system.webServer>
<security>
<requestFiltering>
<verbs applyToWebDAV="false">
<add verb="PUT" allowed="false" />
</verbs>
</requestFiltering>
</security>
</system.webServer>
</configuration>
Whilst working on another problem, I reverse engineered the whole of Microsoft.Owin.Cors to step through it.
It turns out that if the middleware has handled the OPTIONS request then it should return a 2xx and indeed, with the new knowledge of exactly what the middleware needed to see in a request to determine that it was a CORS preflight request, I was able to fake one in Fiddler and get a 2xx.
So, if you get a 405, then double-check.
We seems to be having an issue with a css file caching on the client. I generally stop this from causing issue by adding a version number to the file, i.e.
<link href="Default.css?4.31.0.17051" rel="stylesheet" type="text/css">
But in this circumstance this isn't working and I don't understand why.
The version number was incremented last night from 4.30.0.xxxxx to 4.31.0.17051
Some users, and I've seen it myself, are getting a HTTP 304 response. What's strange is if I inspect it using the IE dev tools it shows a HTTP 304, if I fire up fiddler it doesn't show any request at all.
Content caching is not enabled on the server.
Here's the HTTP header if I do a ctrl-f5:
HTTP/1.1 200 OK
Content-Length: 45861
Content-Type: text/css
Last-Modified: Tue, 23 Jul 2013 14:19:40 GMT
Accept-Ranges: bytes
ETag: "0a61aabaf87ce1:bdba"
Vary: Accept-Encoding
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Date: Tue, 30 Jul 2013 16:05:54 GMT
So:
why don't I see this in fiddler? is it not sending the request at all as this question suggests (https://stackoverflow.com/a/8958279/542251)
Why isn't this cache control (i.e. adding the ?4.31.0.17051 to the file) working?
EDIT
I've now touched the file, to update the Last-modified date but it's still not requesting it.
So the page is returning a HTTP 200, so this isn't the page caching as suggested below:
Request:
GET http://www.mysite.com/Agent/Hotel HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: http://www.mysite.com/Agent/Flights
Accept-Language: en-GB
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: www.mysite.com
Connection: Keep-Alive
Response:
HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 53184
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 3.0
Date: Wed, 31 Jul 2013 08:33:25 GMT
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link href="Default.css?4.31.0.17051" rel="stylesheet" type="text/css" />
.........
As noted in my answer that you cited, the F12 Tools can show a HTTP/304 when the response was really served from the cache. If you don't see the request in Fiddler, it wasn't sent over the network.
Are you sure that the page that refers to the CSS file wasn't pulled from the cache? If it were, then you'd still have the old URL reference. (Look carefully at the CSS request's URL in the F12 tools, as the URL will be accurate even if the "304" was not).
Two points:
- What does "Why isn't this cache control working?" mean? Your HTTP-response headers don't include any Cache-Control directives.
- Changing the Last-Modified date on the server obviously isn't something the client will know about unless it actually issues a Conditional GET request to the server.
So I got a solution but not necessarily an answer.
In the end I updated the tag on the site to:
<link href="Default.css?v=4.31.0.17051" rel="stylesheet" type="text/css">
I'm not sure if adding the v= turning it into a valid querystring was the solution or whether it was just the fact that I altered the URL again solved this issue.
I haven't been able to replicate this issue in staging so I don't really know how or why this started happening.
We have an ASP.NET application running on .NET 3.5 and are running into a problem with the forms authentication cookie not being set on IE9. We can see in the HTTP headers that the Set-Cookie header exists in the response, but the following request does not include that cookie.
I've tried changing every setting in IE that I could find that might relate to cookies and nothing helped. Specifically:
Tools > Options > Security > Trusted Sites > Added..
Tools > Options > Security > Uncheck 'Enable Protected Mode'
Tools > Options > Privacy > Accept All Cookies (lowest)
Tools > Options > Privacy > Sites > Added..
Tools > Options > Privacy > Advanced > Override automatic..
Tools > Options > Privacy > Advanced > Always allow session cookies
Here's the headers for the response with the cookie followed by the next request which doesn't include it:
HTTP/1.1 302 Found
Date: Sun, 29 Jan 2012 01:45:17 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Location: /Default.aspx
Set-Cookie: MyApp=34C244EF0AAD...; expires=Sun, 29-Jan-2012 03:45:17 GMT; path=/
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 8520
GET /Default.aspx HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: http://app.myserver.edu/sec/login.aspx
Accept-Language: en-US
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; MALC)
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: app.myserver.edu
Pragma: no-cache
Cookie: ASP.NET_SessionId=nybswv45aezj5wioscv832jg
Is there any way to find out why IE9 is not setting the cookie? Anything I can adjust in my Web.config that would affect this? My authentication section is this:
<authentication mode="Forms">
<forms name="MyApp" loginUrl="/sec/login.aspx"/>
</authentication>
Simon Svensson was right in his comment. The headers posted above are old, but not as old as the date in the header. The server time is off by a few days so when the server is sending the expires time, even though it's two hours ahead of the server response time, it's past the expiration time according the the client clock.
Fixing the server clock resolved the issue. Thanks Simon!
If you are loading the ASP.NET website within an IFRAME, you will need to include P3P headers. See Cookie blocked/not saved in IFRAME in Internet Explorer
I believe your site is working on Chrome, Firefox etc since you specifically mentioned IE9.
I really hope someone has some ideas. I have set up my web config to cache images for 30 days.
web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlCustom="public" cacheControlMode="UseMaxAge" cacheControlMaxAge="30.00:00:00" />
</staticContent>
</system.webServer>
</configuration>
Yet when I request the page with IE and checkout network traffic this is what I see:
Request Header:
Key Value
Request GET http://www.xx.com/Content/Icons/login.png HTTP/1.1
Accept image/png, image/svg+xml, image/*;q=0.8, */*;q=0.5
Referer http://www.selftestware.com/
Accept-Language en-US
User-Agent Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Accept-Encoding gzip, deflate
Host www.xx.com
If-Modified-Since Wed, 24 Aug 2011 15:48:10 GMT
If-None-Match W/"0195d397562cc1:0"
Proxy-Connection Keep-Alive
Pragma no-cache
Cookie __utma=xx
Response:
Key Value
Response HTTP/1.1 200 OK
Cache-Control public,max-age=2592000
Content-Type image/png
Last-Modified Wed, 24 Aug 2011 15:48:10 GMT
Accept-Ranges bytes
ETag W/"0195d397562cc1:0"
Server Microsoft-IIS/7.5
X-Powered-By ASP.NET
Date Wed, 24 Aug 2011 10:39:14 GMT
Content-Length 727
Should it not send a 304 (not modified). I just can't understand what's wrong here.
Your request header was sent a "Pragma: no-cache" which means told the server not to cache this request. That's why your server response HTTP 200 rather than HTTP 304.
This "Pragma: no-cache" was sent by the browser. If you press Ctrl+F5 hotkey or configured your browser not to cache anything will cause this result. You can try to create a blank page that contains a link to this cached page, then click the link on it. You'll see this page been cached.
I have a request to the server which looks like this:
http://localhost/Combine.aspx/flag/file1.js,file2.js,file3.js
I have also tried this:
http://localhost/Combine.aspx/flag/value/file1.js/file2.js/file3.js
It simply combines the three files which it was given: this works fine.
Upon the first request from Firefox, the page displays correctly. When the page is refreshed again, the content looks like this:
��������`I�%&/m�{J�J��t��`$�����iG#)�*��eVe]f#�흼��{���{��;�N'
In that case, no request is made to the server, the file is only retrieved from the firefox cache, as far as I can tell.
If I force-refresh the page with Control-F5, the page looks normal again.
Here is the request and response (in firebug) with Control-F5 (works):
Response
Cache-Control public
Content-Type application/javascript; charset=utf-8
Content-Encoding gzip
Expires Sun, 26 Feb 2012 02:57:26 GMT
Last-Modified Fri, 07 Jan 2011 21:08:54 GMT
Etag CLYvZwbFmainWEMi8h-6x-zNEIQ1
Vary Accept-Encoding
Server Microsoft-IIS/7.5
Set-Cookie auth=longstring; path=/
X-AspNet-Version 2.0.50727
X-Powered-By ASP.NET
Date Thu, 03 Mar 2011 02:57:26 GMT
Content-Length 918
Request
Host localhost
User-Agent Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.14) Gecko/20110218 Firefox/3.6.14
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/;q=0.8
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
Cookie auth=longstring
Pragma no-cache
Cache-Control no-cache
Here is the same with just F5 (doesn't work):
Response:
Cache-Control public
Content-Type application/javascript; charset=utf-8
Content-Encoding gzip
Expires Sun, 26 Feb 2012 02:57:26 GMT
Last-Modified Fri, 07 Jan 2011 21:08:54 GMT
Etag CLYvZwbFmainWEMi8h-6x-zNEIQ1
Vary Accept-Encoding
Server Microsoft-IIS/7.5
X-AspNet-Version 2.0.50727
X-Powered-By ASP.NET
Date Thu, 03 Mar 2011 03:01:31 GMT
Content-Length 1533
Request:
Host localhost
User-Agent Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.14) Gecko/20110218 Firefox/3.6.14
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/;q=0.8
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
Cookie auth=longstring
The only thing that I can tell is different is the Content-Length (which is likely causing the corruption), but since it never hits the server, I have no control over it.
What could be causing this?
Edit:
This happens on IE8 as well, but instead of viewing a corrupt file, it downloads the corrupt file. No request is ever made to the server (set a breakpoint in visual studio).
As for chrome, when viewing the url directly, a request to the server is made every time, and it works every time. I believe, though, that if it were included in a tag, it would behave similar to Firefox.
Oh, and also:
If I turn off the Expires header (which is one of the flags in the URL), everything works fine.
Edit 2:
I was able to work around this by not sending both an Expires and ETag header, only one or the other. I have no clue why an ETag header would cause such corruption, though.
It is because of your IIS configuration. Adjust IIS as ASP 4.0 Classic, not Default Application Pool