Clearing IIS Cache from MVC3 App

I need to clear the IIS cache on my server.The exact reason is detailed below; but the reason doesn't matter. I'm 100% sure that this is the solution I need; as detailed below, I have used the process of elimination to determine that this is, indeed, the problem I'm facing, and the solution I need.


I have an MVC3 app that's themeable (skinnable architecture). Think of it as Wordpress; users can develop a theme, download it, and activate it on their site. The theme controls exactly the final HTML output. This is an over-simplification, since I provide an API with useful functions to be consumed by themes.

Anyway, users can change the theme of the site. The theme is currently stored in astatic variable. When a view page is rendered, the name of the theme determines the location of the layout file (which contains references to the CSS files, etc.) and the view files. The theme is a setting that persists in the DB.

For example, if I have a theme called "Foo", then when requesting the /Admin page, I might use/Themes/Foo/Admin.cshtml. If I have another theme called "Bar" which does not have that file, then for /Admin it might request/Themes/Bar/Generic.cshtmlas the layout.

The problem is thatchanging a theme means that every single page on the site is outdated.This means that any sites cached on IIS7 will show the old theme; this is incorrect. I need them to show the new theme.

Anyway, IIS7 uses caching by default. I need essentially a way toclear the cache when a user changes the theme.Currently, this is not happening, and users continue to see the old theme until the cache (somehow) expires itself.

I amnotusing output caching, or any other form of explicit caching; this is a "vanilla" ASP.NET MVC3 application from a caching perspective (i.e. I didn't add/configure any caching). IIS7 has its own default caching. I know this, because if I disable output caching in IIS7 for my Site, I will always see the correct theme after a change.

How can I flush the cache? Other SO questions point to usingCache.blah, and I tried usingHttpContext.Currentbut that is null during tests (using VS test tool) -- because the ASP.NET pipeline is not used in full.

To explain, in an integration test, I basically:

  • Go to localhost/Test/
  • Log in (submit values into the forms)
  • Change the theme by browsing to the right page and clicking the right link
  • Request another page
  • See if the theme changed (based on the layout/css file name).

This is all done by code; I use a C# port ofHtmlUnit, and along with deploying my app to /Test in IIS, I can essentially browse it like an end user.

Currently, this test passes around 50% of the time. The problem is that IIS is caching the results, and I can't cleanly reliably reset the cache on the server-side.

Again, I'm not talking about clearing the session or the user-side cache; IIS itself is the culprit guilty of caching my application. Nor do I want to completely disable the cache via the IIS settings, a) because I can't force people who install my application to do that, and b) because caching is good.

So how can I force flushing the cache on the server?

For example, I tried programatically touchingweb.config; this works, but recycles my application pool, and so, kills my static variables; every request means reloading all the static vars from the DB, which kills my performance.

As you requested I have amended this post:

You can use output cache, you say that the selected theme is stored in the database ( like settings for the site ) Well I would add another column with say a GUID and then use this as the varybycustom value.

Your global.asax file will be able to run code:

void Page_Init() {

///code here to get the GUIDforthissitestheme

var outputCacheSettings = new OutputCacheParameters() {
    Duration = Int32.MaxValue, //think its maxvalue
    VaryByCustom = GUIDforthissitestheme
};
InitOutputCache(outputCacheSettings);

}

At least here you will have output cache, but also every change of theme, changes the GUID so therefore changes the cache and then your page should be new.

I did something like this on a site that listed products, and when the products database was updated the key would be changed, however I can't find what site I implemented it and I work on a hell of a lot of sites.

hope this helps

Set up 'Cache Rule' in 'Output caching' feature with 'File Cache Monitoring' set to 'Using file change notification'. Then 'touch' the files theme change affects, from .net code you could do:

System.IO.File.SetLastWriteTimeUtc(fileName, DateTime.UtcNow);

The issues you are describing sound a lot like a client side caching issue. Have you checked this with a HTTP Proxy likeFiddlerto verify if this is getting cached on the client?

If you are seeing HTTP 304's after a template change you may want to try configuring IIS (or your site template) to disable client side caching.

I dont think the approach mentioned for themes is correct. If we are using STATIC variables , then it will affect all the users and all the pages.(Which is certainly not required.)

We can think of two approaches,

  1. Use theme name in url and make it as a prat if RouteData. So the url "http://myHost/BLUE/.." will return in BLUE theme and "http://myHost/RED/.." will return in RED theme. If user will change theme then url will be updated.

  2. The problem with above approach is next time user browse, it will load default theme. So better approach will be save theme as a part of user preference. Once user logged in read the theme from DB and set the RouteData value.

Just touch web.config. That's the easiest and most reliable way. Flushing the application pool programmatically is overkill.

If you have a problem finding out where web.config is in a test environment (sinceSystem.Web.HttpRequest.Currentis null, and similar forServer), you can always use an app.config file to point out the location.

Again, there's no other easy way to do it; even disabling output caching, as mentioned in the question, is hard to do throughweb.configalone.

What Others Are Reading