Disable client side caching - asp.net-mvc

I've been searching for info on how to disable client side caching on project level.
I know I can add the following before an action method:
[System.Web.Mvc.OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
I also read something about making profiles for caching, but that would also mean refering to them in several places. I would like a single setting in web.config, or maybe in IIS?
The project I'm working on contains a lot of partial views
Thank you in advance for any advice in this matter.

You can disable browser caching via Web.Config:
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="no-cache, no-store" />
<add name="Pragma" value="no-cache" />
<add name="Expires" value="-1" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
Source: http://blog.jamesjones.name/2009/11/how-to-disable-browser-caching-in.html
Edit: added no-store to Cache-Control for Chrome ( http://code.google.com/p/chromium/issues/detail?id=28035 )
You can set this at the project level or at the subdirectory level to control browser caching as desired. For example, in a primarily data-driven/dynamic site, I may set these headers at the project level, but in a /static directory (which contains my .js, .css, images), add another web.config which includes the appropriate </clear> directive, and perhaps set a far-future-expires header instead.

You could make BaseController and set your cache profile to it.
Then make all of your controllers to inherit from this BaseController.
Update:
Here is what I've :
// Here is my custom OutputCaheAttribute to prevent cache at all.
//Whatever you may put anything you want.
//Of course i don't use it here but i put it to show you how it's going.
[NoCache]
public class BaseController : Controller
{
protected override ViewResult View(string viewName, string masterName, object model)
{
// I do some stuffs here to change MasterPage depending on current culture.
// Don't care about it i just wanna show you why BaseController is good idea.
}
}
Then ALL my controllers inherits from this BaseController instead of normal Controller.
Hope this was helpful ;)

Expanding on #Tom's answer, for per file or per directory based cache busting :
<configuration>
<!-- disable cache for every file in this directory -->
<location path="dist">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="DisableCache" />
</staticContent>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="no-cache, no-store, must-revalidate, pre-check=0, post-check=0, max-age=0, s-maxage=0" />
<add name="Pragma" value="no-cache" />
<add name="Expires" value="-1" />
</customHeaders>
</httpProtocol>
</system.webServer>
</location>
</configuration>

You can define cache profiles in web.config, however, using cache profiles doesn't seem to work with OutputCache attribute in mvc 3. Read this question: Caching ChildActions using cache profiles won't work?

The OutputCache attribute is used for server side output action output caching. To turn it off, you just don't apply the attribute to the action/controller. If you want to disable client side, then that is taken care of by adding a header informing the browser not to cache the result.

If you need to cache files in a subfolder for 1 day (24 hours), you can add a separate web.config to these sub folders (requires clearing client cache the first time).
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="00:24:00" />
</staticContent>
</system.webServer>
</configuration>

Try this
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]

Related

Extension-less IIS wildcard mapping

I want to configure a wildcard mapping for a specific path, and send the requests to a HttpHandler. My URLs look like this:
http://www.example.com/api/v1/conversation/forums/232?some=value
http://www.example.com/api/v1/conversation/posts/212
This configuration doesnt match the URLs above.
<location path="api/v1/conversation">
<system.webServer>
<handlers>
<add name="ApiProxy" verb="*" path="*" preCondition="integratedMode" type="DemoProject.ApiProxy, DemoProject" />
</handlers>
</system.webServer>
</location>
It works when I add an extension to my URLs:
http://www.example.com/api/v1/conversation/forums/232.axd?some=value
http://www.example.com/api/v1/conversation/posts/212.axd
How do I make this work extension-less?
It turned out, that this problem was related to my website was running Umbraco CMS. Umbraco CMS has an AppSetting called "umbracoReservedPaths", which asks Umbraco to ignore specific paths.
The value was set to:
<add key="umbracoReservedPaths" value="~/umbraco,~/install/" />
After adding ~/api/, everything worked as expected:
<add key="umbracoReservedPaths" value="~/umbraco,~/install/,~/api/" />

YSLOW Expiry Headers on MVC 5 Web Site

I used YSlow to test an ASP.NET MVC web site and I got the error:
"Add Expiry Headers" for the following items:
(no expires) http://www.mydomain.pt/assets/logo.png
(no expires) http://www.mydomain.pt/favicon-196x196.png
(2013/12/30) http://www.mydomain.pt/file/e6fb9d2a-668b-423a-9120-0b34228f296c
What is strange is that I addressed these issues. For static I used:
CORRECTED
<system.webServer>
<clientCache setEtag="false" cacheControlMode="UseMaxAge" cacheControlMaxAge="60.00:00:00" />
</system.webServer>
And for the file, returned by an action, I have:
[Route("file/{identifier:guid}"), HttpGet, OutputCache(Duration = 1200, Location = OutputCacheLocation.Client, VaryByParam = "identifier")]
public virtual ActionResult Get(Guid identifier, String n = null) {
}
Does anyone knows why I still have no cache on these items?
Am I missing something?
Thank You,
Miguel
Use following syntax:
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="60.00:00:00" />
</staticContent>
</system.webserver>
Compressing static files doesn't have anything to do with expiration headers. Compression is related to GZip.
The reason the .png files do not have the Expiry header that you are setting in the action method, is that MVC is not being used to serve the static files, so it will not set the headers.
Add expires header to images

Orchard CMS 1.7 Custom Theme images not loading

I had started creating a new theme while using v1.6.1.
Things were not going well with a custom module creation so I decided to start from scratch. This time I am using the source from V1.7
I copied my custom theme folder, pasted it into the themes folder of the new 1.7 project and ran the site. I could see the theme in my dashboard so I set it to the current theme.
Now when I view my site NONE of the images are loading. The style sheets are loading, though none of the images - either from the style sheet or from any views - are loading.
My images are in myTheme/content/images - which as I understand it is how 1.6.1 required things to be laid out.
My content folder has a web.config as does my images folder. It's the same config used in 1.6.1 so I'm wondering if something has changed.
In one of my theme views I have the following code - this worked in 1.6.1:
<img src="#Url.Content(Html.ThemePath(WorkContext.CurrentTheme,"/Content/Images/phoneBullet.png"))" alt="T:" />
If I output this to my front-end I get:
~/Themes/PerformanceAbrasives/Content/Images/phoneBullet.png
This tells me things appear to be in the correct place - though I'm wondering if my web.config is now out of date?
I have this - there is a copy in content and a copy in images:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
</staticContent>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>
Any pointers?
UPDATE
Ok... so if I set my project to use Visual Studios internal development server then all is well - if I tell it to use Local IIS Web server - use IIS Express (http://localhost:30333/) - then it doesn't work...
UPDATE 2
Ok - now running from IIS 7 and images do not load... stylesheets seem ok, but images are not.. grrr
any ideas so I don't run into this problem when I deploy?
Ok - I figured it....
You only need the web.config in my Content directory - not in both content AND images

Is there any way to have a file extension in a bundle name?

I would like to have define a bundle like this:
bundles.Add(
new StyleBundle("~/style.css").Include(
//...
));
If the bundle name is just "~/style" this works, but with the file extension it always returns a 404. I suspect the server searches for CSS and JS files on the drive and ignores the bundling system, but I can't find anyone else who is trying to include file extensions in bundle names. Is this possible to do without something like a URL rewrite?
You could add the following to your <system.webServer> section in web.config:
<modules runAllManagedModulesForAllRequests="true" />
This will ensure that requests for static resources such as .js and .css will pass through the managed modules and be intercepted by ASP.NET MVC.
As an alternative to enabling runAllManagedModulesForAllRequests for all requests you could configure them only for the urls you need to use. So inside the <handlers> add the following:
<handlers>
<!-- ... -->
<add name="scriptBundle" verb="*" path="script.js" type="System.Web.Optimization.BundleHandler, System.Web.Optimization" preCondition="managedHandler" />
<add name="cssBundle" verb="*" path="style.css" type="System.Web.Optimization.BundleHandler, System.Web.Optimization" preCondition="managedHandler" />
</handlers>

Crystal Reports Images and ASP.Net MVC

I am having trouble with Crystal Reports when using charts and images which use CrystalImageHandler.aspx. The image cannot display and I suspect this is due to a problem with MVC routing.
The path image path is similar to this:
src="/CrystalImageHandler.aspx?dynamicimage=cr_tmp_image_a8301f51-26de-4869-be9f-c3c9ad9cc85e.png"
With the URL similar to this:
localhost:01234/ViewCrystalReports.aspx?id=50
The image cannot be found prumably because it's looking in a non-existant directory. How can I change the path CrystalImageHandler.aspx is located at? I think if I were to reference from the root the problem would be solved but anything I change in Web.Config fails to work.
I should mention this is on a conventional aspx page, not a view etc
I solve this problem editing Web.Config file
Insert the following line:
<system.web>
...
<httpHandlers>
<add path="CrystalImageHandler.aspx" verb="GET" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"></add>
</httpHandlers>
...
*take care with write your number version (Version=xx.x.xxxx.x)
Figured it out. The routing was interfering with the CrystalImageHandler.aspx link that was being generated. Global.aspx has the following line to tell the routing engine to ignore resource files:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
but this isn't a conventional resource file, it's an aspx file for some reason (anyone know why?)
adding this fixed it:
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
public class CrystalImageHandlerController : Controller
{
//
// GET: /Reports/CrystalImageHandler.aspx
public ActionResult Index()
{
return Content("");
}
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
var handler = new CrystalDecisions.Web.CrystalImageHandler();
var app = (HttpApplication)filterContext.RequestContext.HttpContext.GetService(typeof(HttpApplication));
if (app == null) return;
handler.ProcessRequest(app.Context);
}
}
This controller will invoke the handler. Just add a route to this as CrystalImageHandler.aspx, it can also be used with any sub path you'd like (in this case /reports). Something I could NEVER get the handler to do via configuration.
To view in local machine,you will add the following code in web config
<httpHandlers>
<add verb="GET" path="CrystalImageHandler.aspx" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web,Version=10.2.3600.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" />
</httpHandlers>
...............................
<appSettings>
<add key="CrystalImageCleaner-AutoStart" value="true" />
<add key="CrystalImageCleaner-Sleep" value="60000" />
<add key="CrystalImageCleaner-Age" value="120000" />
</appSettings>
The following code is for displaying in server
<system.webServer>
<handlers>
<add name="CrystalImageHandler.aspx_GET" verb="GET" path="CrystalImageHandler.aspx" type="CrystalDecisions.Web.CrystalImageHandler, CrystalDecisions.Web, Version=10.2.3600.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" preCondition="integratedMode"/>
</handlers>
</system.webServer>
:) I will solve that problem in adding in web config
It's because the routing was interfering with the CrystalImageHandler.aspx. So either in Global.asax or routeConfig file we can ignore route for .aspx extension files. You can ignore .aspx extension route by adding following line.
routes.IgnoreRoute("{allaspx}", new {allaspx=#"..aspx(/.*)?"});

Resources