Why aren't my images caching? - asp.net-mvc-3

I have an ASP.NET MVC3 application setup. There is a controller that returns back images and I have added the following:
[OutputCache(Duration = 3600, VaryByParam = "id;width", Order = 1000, Location = OutputCacheLocation.Client)]
public ActionResult Get(string id, int width)
{ ... }
But when I check out the HTTP Response on these images they all have headers that say "cache-control: no-cache" and "expires: -1" which means the browser is never caching them.
I'm looking all around and I can't find anything on why the response is telling the browser not to cache them. I even tried working up my own attribute that did:
public class ContentExpiresHeader : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
var cache = filterContext.HttpContext.Response.Cache;
cache.SetExpires(DateTime.Now.AddYears(1));
cache.SetCacheability(HttpCacheability.Private);
cache.SetLastModifiedFromFileDependencies();
base.OnResultExecuted(filterContext);
}
}
but that didn't get me anywhere either.
Any help is appreciated.
UPDATE: I'm starting to think this has got to be an IIS setting somewhere that is adding the no-cache and overriding. I can't seem to find anything, though. The only odd thing is that if I take a look at the state of the cache variable after I've called the .Set...() methods the internal variables have not been updated. I would have expected something to change but they're still showing "no-cache".
UPDATE 2: I should add that the return of this method is a:
return File(...);
UPDATE 3: I also found this (http://dotnetslackers.com/articles/aspnet/ASP-NET-MVC-3-Controller-for-Serving-Images.aspx) and tried implementing it without any luck. Still getting the no-cache options on the response header for the images.
UPDATE 4: Just had to check server settings... if I bypass my controller and go straight to an image file on the server, then it DOES cache and has the correct caching settings in the response header.
UPDATE 5 (yeah, getting crazy): Created a brand new MVC3 project and just made the one controller and it cached just fine. So I've got something outside the immediate code that is adding this pragma:no-cache stuff and for the life of me I can't figure out what it'd be. =-/

Try changing the cacheability from HttpCachability.Private to HttpCachability.ServerAndPrivate. It should keep the cache-control as private and not suppress e-tags/last modified.

Found the problem! And it's the weirdest thing I've seen in a while.
I am using SocialAuth-net and somewhere during the setup I added the system.webServer module for it and set runAllManagedModulesForAllRequests=true. I thought, "huh, wonder if that's causing it somehow", as I couldn't reproduce the problem outside this particular app. Low and behold, commenting out that section of the config and my images started caching! Hoorah!
But, it gets weirder. I undid my config changes, refreshed and now I'm still getting caching. I can't tell you how many resets of the system I've done with no change but somehow temporarily removing these modules from the pipeline seems to have resolved this problem.
I can track it down to the SocialAuthHttpModule and if I remove it SocialAuth-net still seems to work but caching is restored reliably. Very weird.

Related

MVC3 SSL Trouble - Can't switch from HTTPS to HTTP when SSL is not required

I'm trying to get my MVC3 site to redirect from HTTPS back to HTTP when the user browses to a page where it's not required (and they aren't logged in). I Don't want to have the load of running the whole site HTTPS but it's looking like thats the way I'll have to go.
I've been having loads of trouble with remote debug and symbols, but having gone back in time to 1985 and using message box equivalents to debug with I've come to the following conclusion:
if (filterContext.ActionDescriptor
.GetCustomAttributes(typeof(RequireHttpsAttribute), true)
.Any()
)
{
return true;
}
return false;
Always returns false.
The controller def starts as:
[FilterIP(
ConfigurationKeyAllowedSingleIPs = "AllowedAdminSingleIPs",
ConfigurationKeyAllowedMaskedIPs = "AllowedAdminMaskedIPs",
ConfigurationKeyDeniedSingleIPs = "DeniedAdminSingleIPs",
ConfigurationKeyDeniedMaskedIPs = "DeniedAdminMaskedIPs"
)]
[RequireHttps]
public class AccountController : Controller
{
And it doesn't seem to work for any actions in this controller (although they do get successfully routed to SSL).
Any suggestions? I'd love to see an answer for what I perceive as my own nubery ;)
Custom NotRequreHttpsAttribute tutorial
I use the above link post to implement my custom attribute, and redirect from https to http. Hope this helps.
My problem was discovered to be related to the bindings on the server published to. We use the same server for stage and production, and the stage https bindings were not set, so whenever it was calling an https page it was resolving into our production site (which looked the same so it was hard to spot).
Once I added a binding it was all solved. My code was ok...

MVC3 OutputCache not working on Server and Client as expected

I'm having trouble using the OutputCache attribute in Microsoft's MVC3 framework.
Please imagine the following controller action, which can be used as part of an AJAX call to get a list of products based on a particular manufacturerId:
public JsonResult GetProducts(long manufacturerId)
{
return Json(this.CreateProductList(manufacturerId), JsonRequestBehavior.AllowGet);
}
I want this result to be cached on the server to avoid making excessive database queries. I can achieve this by configuring the attribute thus:
[OutputCache(Duration = 3600, Location = OutputCacheLocation.Server, VaryByParam = "manufacturerId")]
This works as I expected - the browser makes an intitial request which causes the server to create and cache the result, subsequent requests from the same or different browser get the cached version.
But... I also want the browser to cache these results locally; if I filter first on manufacturer X, then Y then go back to X, I don't want it to make another request for X's products - I want it to just use its cached version.
I can make this happen, by changing the OutputCache to this:
[OutputCache(Duration = 3600, Location = OutputCacheLocation.Client)]
Here's the question: how do I combine these so that I can have both sets of behaviour? I tried setting the Location to ServerAndClient but this just made it behave the same as when Location was Server.
I'm sure that the problem has something to do with the "Vary: *" response header I get with ServerAndClient but I don't know how to get rid of it.
I welcome comments about the rationality of my intentions - the fact that I'm not getting the results I expect makes me think I might have some fundamental misunderstanding somewhere...
Many thanks.
PS: This is on a local dev environment, IIS Express from VS2010.
You can use OutputCacheLocation.Any which specifies
The output cache can be located on the browser client (where the
request originated), on a proxy server (or any other server)
participating in the request, or on the server where the request was
processed. This value corresponds to the HttpCacheability.Public
enumeration value.
You may want to also set Cache-control public to in the HTTP header for these requests.
Edit
It seems, depending on your .Net version of the web server you may need to include Response.Cache.SetOmitVaryStar(true); within your controller action to remove the Vary * headers as you suggest.
Details of the reason why in .Net 4 breaking changes release notes.

Caching images, CSS and JS resources in Wicket 1.5.3

I am trying to optimize the performance of a Wicket 1.5.3 application.
I'm trying to get the caching configuration up and running. I've already reviewed "migration to 1.5" papers, the migration guide and samples. I've also ensured that there is a default caching strategy available, and tried to set a custom one.
getResourceSettings().setCachingStrategy(strat);
The app has CSS and JS in a Base-Frame.html header as link and script, and it has a lot of images. I'm currently using something like this:
Image img = new Image("logoutImg") {
protected void onComponentTag(ComponentTag tag) {
super.onComponentTag(tag);
tag.put("src", baseUrl + "/images/logout.png");
}
};
With that, the HTTP header output is always:
Pragma No-cache
Cache-Control no-cache
for all resources and pages.
I've now implemented some servlet filters, which is a rather brutish method that avoids all previously set Wicket headers.
Could anyone provide a running working example, or some tips for getting this up and running? In particular, something using FilenameWithVersionResourceCachingStrategy would be really helpful, since that seems to be a good solution.
I guess you have to use Wicket's CachingImage class allowing you to set the headers accordingly to the browser

Let the mvc-mini-profiler ignore Glimpse requests

I'm using mvc-mini-profiler along with Glimpse. The problem is glimse is flooding the profiler output with glimpse requests. Is there any way to ignore all request made by glimpse ?
protected void Application_Start()
{
var ignored = MiniProfiler.Settings.IgnoredPaths.ToList();
ignored.Add("Glimpse.axd");
MiniProfiler.Settings.IgnoredPaths = ignored.ToArray();
}
Solution Posted here:
Mini MVC profiler: appears to be displaying profile times for every static resource
At the moment Glimpse will make Ajax requests if you have the Remote tab selected or when ever an Ajax request is made by your site.
This is done because when we detect that a request is made we proactively get the Glimpse data. We could probably switch this in a future release to be more lazy and only fetch the data on request.
Note, even though this will help, Glimpse will still be calling back to the server in the same way that Mini Profile does. Hence, both frameworks could probably try and ignore each other for ajax requests.
Hope this helps.

ASP.NET MVC2 and Browser Caching

I have a web application that fetches a lot of content via ajax. For example when a user edits some data, the browser will send the changes using an ajax post and then do an ajax get to get fresh content and replace an existing div on the page with that content. This was working just find with MVC1, but in MVC2 I would get inconsistent results.
I've found that MVC1 by default included an Expires item in the response headers set to the current time, but in MVC2 the Expires header is missing. This is a problem with some browsers (IE8) actually using the cached version of the ajax get instead of the fresh version.
To deal with the problem I created a simple ActionFilterAttribute that sets the reponse cache to NoCache (see below), which works, but it seems kind of sillly to decorate every controller with this attribute. Is there a global way to set this for every controller?
Is this a bug in MVC2 and it really should be setting the expires on every ActionResult/view/page? Don't most MVC programs deal with data entry where stale data is a very bad thing?
Thanks
Dan
public class ResponseNoCachingAttribute : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
filterContext.HttpContext.Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
}
}
Have you tried adding the following attribute to your controller?
[OutputCache(Location = OutputCacheLocation.None)]

Resources