Output Cache not caching all pages - iis-7

I have a cache rule in a directory by file extension and there are 2 dynamic pages in that directory.
<configuration>
<system.webServer>
<caching>
<profiles>
<add extension=".asp"
policy="CacheForTimePeriod"
kernelCachePolicy="DontCache"
duration="03:00:00"
location="Any"
varyByQueryString="*" />
</profiles>
</caching>
</system.webServer>
</configuration>
There really isn't a significant difference between the two, they both run off querystrings, however, IIS doesnt want to cache one of them for some reason I can't figure out why. One of the pages it caches perfectly, but the other it doesn't. I was thinking it may have been due to the output filesize, since the page being cached is always under 256kb and the other is usually over, and 256kb is the default setting in MaxCachedFileSize. So I added the following registry as per ms suggestions:
HKLM\System\CurrentControlSet\Services\InetInfo\Parameters\MaxCachedFileSize
I set it to 10485760 bytes (10mb), since default is 256kb. Still not caching. As I said, the other file in the same dir caches fine, but the other one doesn't. Not sure what it could be, there is barely any memory being used on the server, so I don't think this can be a memory space not available issue.
Also, I've read that sending cookies in the page can cause IIS not to cache the page, but neither of the pages are sending cookies.

Removing Response.Flush from the page did the trick for anyone else in the future.

Related

How to set cache headers for files accessed directly

I have a server that serves WAV file to Twilio and I am having some problems to set the cache to those files.
My problem is that the files have different expiration date, some shouldn't be cached, some should be cached for a day, some for a month and so on.
At the moment I was able to set to not cache any of the files using the IIS Output Caching, however now I need to set some caches.
Basically Twilio request the WAV files calling it directly, for example, http://mywebsite.com/mysoundwithoutcache.wav as well as http://mywebsite.com/mysoundwith1daycache.wav and so on.
My question is how do I add this headers to those files that are been called directly?
I am using IIS 7 and ASP.NET
Thanks in advance
The way to apply settings just to a certain files is to use the location tag, in your web.config add a new node under configuration:
<location path="cache_me.wav">
<system.webServer>
<caching>
<profiles>
<add extension="*.wav" policy="CacheForTimePeriod" kernelCachePolicy="DontCache" duration="01:00:00" />
</profiles>
</caching>
</system.webServer>
</location>
Unfortunately I don't think you can use wildcards in the path attribute, so you one of these sections for each file. If would be easier to put all files to be cached into a separate folder, then you can get away with a single location node.
Having said all that, you should not worry about output caching for your waves files, static files are cached by IIS automatically.

IIS and Static content?

According to Ultra-Fast ASP.NET: Chapter 3 - Caching:
Files that the browser retrieves from the server should be stored in
the browser’s cache as long as possible to help minimize server
round-trips.
But how does IIS know what a static content actually is and is not?
Is it just images, CSS, JS and not ASPX, ashx...?
Where can I see in IIS what is already considered to be static and what is not ?
What about the scenario where a page has been declared with <%# OutputCache header (without location)? Are the images, CSS and JS source files inside of it also being output cached with the same properties?
As a best practice, I should set one year into the future as the maximum expiration time. I should use that as the default for all static content on the site
So I did this :
But later, after pressing OK, I can't find any summary menu which shows me: to whom I already put a response header (in this case: the css folder).
Currently, in order to see that css folder has been applied with response headers - I have to go to the css folder again --> Http Response Header-->Set Common Headers --> and then I see it. It isn't written in the web.config.
But if I do it for a file (Login.aspx for example): I do see it in web.config:
<configuration>
<location path="Login.aspx">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseExpires" cacheControlMaxAge="1.00:00:00" httpExpires="Fri, 15 Feb 2013 00:00:00 GMT" />
</staticContent>
</system.webServer>
</location>
</configuration>
I understand your situation. Sometime its confusing how IIS handles a file. Its also different for IIS 6 vs IIS 7 and different for Classic App Pools and Integrated mode app pools. My experience is mostly with Integrated App Pools on IIS 7.5, so thats the environment I can comment on most accurately.
First Question
But how does IIS knows what is actually a static content and what is
not?
Is it just images , css , js and not ASPX , ashx...?
Where can I see in the IIS what is already considered to be static and
what not ?
You can inspect the list of file handlers in IIS by navigating to your website and then click 'Handler Mappings'. By default these are inherited from the .Net base web.config which is in a different location depending on your .Net framework version.
C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config
If a file being requested isn't already explicitly mapped to another handler it falls to a catch all handler (*) as the last option (System.Web.DefaultHttpHandler) which determines if it is a static file or a directory browsing request. So Static files are simply files not bound to another handler already. For example you'll see that *.aspx is already mapped to System.Web.UI.PageHandlerFactory prior to this default handler. So its going to be processed by that handler and not be considered a static file. If you removed that mapping you could technically serve *.aspx as a static file if you really wanted to (just for proof of how it works).
But you can also explicitly list a file type as a static file by adding an entry in your web.config's httpHandlers section mapping the file extensions to System.Web.StaticFileHandler in IIS. For example:
<configuration>
<system.webServer>
<handlers>
<add name="StaticHandler" verb="*" path="*.zip" type="System.Web.StaticFileHandler" preCondition="integratedMode" />
</handlers>
</system.webServer>
</configuration>
This example is using the <system.webServer> config section, so its for an App Pool running in Integrated Mode.
Second Question
What about the scenario where a page has been declared with <%#
OutputCache header(without location) . does the images,css,js src
files inside of it , are also being output cached with the same
properties?
No. Because the page is being server as a separate request (maybe even by a separate handler) it can have totally different cache headers/hints. The host page and the resources it may use are not related from a caching perspective.
In fact you may even want to have a shorter cache period for *.html and a longer cache period for *.jpg or *.png? Something to consider.
Third Question
As a best prcatice , I should set one year into the future as the
maximum expiration time.I should use that as the default for all
static content on the site
Hmm... I might not go as far as one year. How about one month? I would set a global policy like this:
<configuration>
<system.webServer>
<staticContent>
<!-- Set expire headers to 30 days for static content-->
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="30.00:00:00" />
</staticContent>
</system.webServer>
</configuration>
This is the same as the sample you showed above, but is not inside a <location> element, instead it is right in the root <configuration> element so it is the default policy. Again this is for an App Pool running in Integrated Mode. Sometimes you also need to turn on:
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<!-- stuff -->
</modules>
</system.webServer>
<system.webServer>
This just makes sure that static files are processed through the managed static file handler which respects the above configuration elements.
Edit to Address Comments
The documentation for the configuration dialog you posted above is located here: Configure the HTTP Expires Response Header (IIS 7)
Apparently these settings are saved in C:\Windows\System32\inetsrv\config\applicationHost.config
I do not have IIS7 and personally develop on IIS 7.5 now. So please post a comment if you can verify this location is accurate!
The static content is the one that IIS is read and send to the browser with out any processing. There you can setup IIS to include some Cache-Control Header to cache it on clients browser computers.
You can do that ether by direct setup IIS, ether by commands on web.config as you say. The commands that you add on web.config and concern the IIS, did not have to do with asp.net it self, but the IIS, and IIS saves his configuration on a different file, so when you change that cache control headers direct on IIS you do not see them on web.config.
Now for the static content like images, CSS, JavaScript, and other similar files they say that you can follow the "never expire" policy by adding 10 years expire.
The issue here is that if you can not change the content of the static file, if for example you cache a javascript file with 10 years, and you make a small change on it, then you need ether to change the file name, ether to add some parameter at the end of it.
Now the <%# OutputCache on a control is referred to the server cache and not to the client, and what is actually do is to cache the render of the control on the server so the next time you ask it to not lose time to renders it again but read it from cache - is still send it to the browser.
And you can also read this answer for some more: What are difference between IIS (Dynamic and Static) cache,OutPutCache and browser cache

Custom Sharepoint webservice requires web.config to be "touched" regularly

We have a site running on MOSS 2007 which makes calls to custom web service asmx methods on the same domain from the client.
At first everything works fine, but after a bit of time has passed the service will start to fail with:
http://[domain]/_layouts/error.aspx?ErrorText=Request format is unrecognized for URL unexpectedly ending in %27%2FIsSuspectWaterLevel%27.
Interestingly enough
http://[Domain]/_vti_bin/Custom/CustomFunctionality.asmx?op=IsSuspectWaterLevel
is still available, but a call to
http://[Domain]/_vti_bin/Custom/CustomFunctionality.asmx/IsSuspectWaterLevel
will fail as described.
We've found that "touching" C:\Program Files\Common Files\microsoft shared\Web Server Extensions\12\ISAPI\ web.config will bring the webservice back to life.
The asmx file lives at
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI\ECan\MyECan_ComplianceWaterUsage.asmx
Any ideas of what might be going on here and how to resolve them?
Some extra detail:
App pool settings in case they're useful: http://i51.tinypic.com/x51qw.png
The following web.config settings are present in the root and sub directory hosting the asmx:
<system.web>
<webServices>
<protocols>
<add name="HttpSoap" />
<add name="HttpGet" />
<add name="HttpPost" />
</protocols>
</webServices>
...
</system.web>
We are calling the web service from javascript (jQuery). I've checked all the settings mentioned in this link and all match. I think calling from javascript may not be the culprit though as going directly to
[domain]/_vti_bin/Custom/CustomFunctionality.asmx/IsSuspectWaterLevel
with parameters supplied also fails with the same error - no javascript involved. Failing after a short period of time has passed, but works fine when web.config has just been "touched" again.
Thanks in advance for any help! Cheers, Gavin
I'm currently working on the same problem, and I think you barked the wrong tree.
The problem is, that in the ISAPI folder of SharePoint is a web.config with the following lines:
<webServices>
<protocols>
<remove name="HttpGet"/>
<remove name="HttpPost"/>
<remove name="HttpPostLocalhost"/>
<add name="Documentation"/>
</protocols>
</webServices>
The problem is, that the desired protocols POST and GET will be removed for the entire ISAPI folder and its subfolders. I also tried to reactivate the protocols via
<location path="[Path to my Web Service].asmx" allowOverride="false">
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
</loaction>
in different places (machine.config, web.config of root folder, web.config app.config, ...), but it didn't last.
The only thing that worked, was, to change the "remove" items in the web.config of the ISAPI folder to "add" items.
But this has the nasty side effect, that the built-in web services, like "Lists.asmx" throw errors if you try to request their documentation pages...
If you can live with that, this would be your solution. I can't, so I still try to figure out a way to make my
<add name="protocol">
items persistent.
By the way: Also adding lockItem="true" to the <add/> items didn't do the trick...
Chris
It has been awhile since I have touched Sharepoint so this is a shot in the dark. If I remember correctly modifying anything in the web.config will restart the website in IIS. So what you may be seeing is IIS restarting the website that hosts the webservice putting it back into a good state.
Do you have the following in the web.config for the web application?
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
This is a strange problem and hard to diagnose due to the number of occcurances of the 12 hives web.config protocols issue which would appear to resolve 99% of the cases of this issue.
There is another issue called URL rewriting that will cause this
problem.
Some reverse proxy devices can modify the path of a request (the
portion of the URL that comes after the hostname and port number) in
such a way that a request sent by the user to
http://www.contoso.com/sharepoint/default.aspx, for example, is
forwarded to the Web server as
http://sharepoint.perimeter.example.com/default.aspx.
This is referred to as an asymmetrical path. Windows SharePoint
Services 3.0 does not support asymmetrical paths. The path of the URL
must be symmetrical between the public URL and the internal URL. In
the preceding example, this means that the "/sharepoint/default.aspx"
portion of the URL must not be modified by the reverse proxy device.
Even more depressing is that microsoft knows about this and actively refuses to support it.
Ref: URL Rewrite + SharePoint = No Support
Also : SharePoint, url rewriter, WebServices
An inelegant workaround to this issue that works for us: We've swapped out the web service asmx end point for a web handler ashx endpoint. This doesn't suffer the same issue for some reason.
I'm guessing from this that there's some issue creeping in after a period of time which is causing urls to resolve incorrectly. I suspect that the / after the .asmx in the url is the curprit. The ashx endpoint implemented is working purely on url parameters and posted data.
Obviously this work around won't always be an option for others who might experience the same issue as we're loosing a lot of the rich web service functionality that's pre-baked in to an asmx endpoint.
Unfortunately I won't be able to test any other solutions that people might put forward from now on as we've moved away from the web service asmx approach. Sorry. Thanks for all the suggestions though - it's been very much appreciated!

Basic authentication in asp.net avoided if runAllManagedModulesForAllRequests="True"

We have one module which does internal redirection to real aspx pages. He is also in charge for directly serving cached/compressed HTML/txt/cs/js output to client.
Here is how web.config looks like for modules section:
<modules runAllManagedModulesForAllRequests="True">
<remove name="RequestInterceptor" />
<add type="Lib.Request.RequestInterceptor" name="RequestInterceptor" />
<remove name="Session" />
<add type="System.Web.SessionState.SessionStateModule" name="Session" />
</modules>
Basic authentication is turned on on IIS7. When first visitor comes to site login popup shows and he is correctly authenticated, and then pages which he visits get cached.
When next visitor comes authentication pop up doesn't show up, unless he visits a page which was not visited by previous visitor (page that is not cached). Once the cache has expired, authentication works again until the page content gets cached, and so on.
Is there a way to force authentication for every visitor? Maybe we need to add basic authentication module to module section of web.config (how to do that)?
Thanks in advance.
Cheers
While searching for an answer to a related question I came across this post:
Don't use runAllManagedModulesForAllRequests="true" when getting your MVC routing to work
It seems to be common advice to make your modules section of your
web.config say . In
fact this is quite a drastic thing to do to solve the routing problem
and has global effects that could CAUSE ERRORS. ... This highly
recommended fix can cause other problems. These problems come in the
form of making all your registered HTTP modules run on every request,
not just managed requests (e.g. .aspx). This means modules will run on
ever .jpg .gif .css .html .pdf etc.
And, while I'm not using MVC in my WCF REST Service, it did fix my (other) problem and this advice against inappropriate or overuse of runAllManagedModulesForAllRequests may be warranted.
Because httpmodule intercepts each request, server is not able to map appropriate handler for static files, dynamic files, and among others secuirty authentication.

Enable all caches except asp net output cache

I have different urls that points to the same code
www.url1.com
www.url2.com
I need to use the cache, but if the asp net cache is enabled when someone access to www.url1.com next person accessing www.url2.com could get the previously cached data (www.url1.com)
I need to have ALL caches activated except this one.
You can disable ASP.Net output caching for the entire application by putting it in your web.config file.
<configuration>
<system.web>
<caching>
<outputCache enableOutputCache="false">
</outputCache>
</caching>
</system.web>
</configuration>
But unless you're actually putting anything in the cache in the first place, you don't have anything to worry about.

Resources