从 MVC3 应用程序清除 IIS 缓存
我需要清除服务器上的 IIS 缓存。具体原因如下所述;但原因并不重要。我 100% 确定这就是我需要的解决方案;如下详述,我使用排除法来确定这确实是我面临的问题,也是我需要的解决方案。
我有一个可主题化的 MVC3 应用程序(可换肤架构)。将其视为 WordPress;用户可以开发主题、下载主题并在其网站上激活它。主题精确控制最终的 HTML 输出。这是一种过度简化,因为我提供了一个 API,其中包含可供主题使用的有用函数。
无论如何,用户可以更改网站的主题。主题当前存储在静态变量中。当渲染视图页面时,主题的名称决定了布局文件(其中包含对 CSS 文件等的引用)和视图文件的位置。主题是保留在数据库中的设置。
例如,如果我有一个名为“Foo”的主题,那么在请求 /Admin 页面时,我可能会使用 /Themes/Foo/Admin.cshtml
。如果我有另一个名为“Bar”的主题,但没有该文件,那么对于 /Admin 它可能会请求 /Themes/Bar/Generic.cshtml
作为布局。
问题是,更改主题意味着网站上的每个页面都已过时。这意味着 IIS7 上缓存的任何网站都将显示旧主题;这是不正确的。我需要他们来展示新主题。
不管怎样,IIS7默认使用缓存。我本质上需要一种方法来当用户更改主题时清除缓存。目前,这种情况没有发生,用户会继续看到旧主题,直到缓存(以某种方式)自行过期。
我没有使用输出缓存或任何其他形式的显式缓存;从缓存的角度来看,这是一个“普通”ASP.NET MVC3 应用程序(即我没有添加/配置任何缓存)。 IIS7有自己的默认缓存。我知道这一点,因为如果我在 IIS7 中为我的站点禁用输出缓存,那么在更改后我将始终看到正确的主题。
如何刷新缓存?其他SO问题指向使用Cache.blah
,我尝试使用HttpContext.Current
,但在测试期间为空(使用VS测试工具)——因为ASP.NET管道没有得到充分利用。
为了解释一下,在集成测试中,我基本上:
- 转到 localhost/Test/
- 登录(将值提交到表单中)
- 通过浏览到右侧页面并单击右侧链接来更改主题
- 请求另一个页面
- 查看主题是否已更改(基于在布局/css 文件名上)。
这一切都是通过代码完成的;我使用 HtmlUnit
的 C# 端口,并将我的应用程序部署到 IIS 中的 /Test,我基本上可以像最终用户一样浏览它。
目前,该测试的通过率约为 50%。问题是 IIS 正在缓存结果,而我无法在服务器端干净可靠地重置缓存。
再说一次,我不是在谈论清除会话或用户端缓存;而是在谈论清除会话或用户端缓存。 IIS 本身是缓存我的应用程序的罪魁祸首。我也不想通过 IIS 设置完全禁用缓存,a) 因为我不能强迫安装我的应用程序的人这样做,b) 因为缓存很好。
那么如何强制刷新服务器上的缓存呢?
例如,我尝试以编程方式触摸 web.config
;这可行,但会回收我的应用程序池,因此会杀死我的静态变量;每个请求都意味着从数据库重新加载所有静态变量,这会降低我的性能。
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 a static 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.cshtml
as the layout.
The problem is that changing 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 to clear 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 am not using 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 using Cache.blah
, and I tried using HttpContext.Current
but 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 of HtmlUnit
, 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 touching web.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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
按照您的要求,我修改了这篇文章:
您可以使用输出缓存,您说所选主题存储在数据库中(如网站的设置)好吧,我会添加另一列,其中包含 GUID,然后将其用作 Varbycustom价值。
您的 global.asax 文件将能够运行代码:
}
至少在这里您将拥有输出缓存,而且每次主题更改都会更改 GUID,因此会更改缓存,然后您的页面应该是新的。
我在列出产品的网站上做了类似的事情,当产品数据库更新时,密钥将会更改,但是我找不到我实现它的网站,而且我在很多网站上工作。
希望这有帮助
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:
}
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
在“输出缓存”功能中设置“缓存规则”,并将“文件缓存监控”设置为“使用文件更改通知”。然后“触摸”文件主题更改影响,您可以从 .net 代码执行以下操作:
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:
您描述的问题听起来很像客户端缓存问题。您是否使用像 Fiddler 这样的 HTTP 代理检查过此内容,以验证这是否已缓存在客户端上?
如果您在模板更改后看到 HTTP 304,您可能需要尝试配置 IIS(或您的站点模板)以禁用客户端缓存。
The issues you are describing sound a lot like a client side caching issue. Have you checked this with a HTTP Proxy like Fiddler to 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.
我认为主题提到的方法不正确。
如果我们使用 STATIC 变量,那么它将影响所有用户和所有页面。(这当然不是必需的。)
我们可以想到两种方法,
在 url 中使用主题名称,如果 RouteData 则将其作为 prat 。因此,url“http://myHost/BLUE/..”将在蓝色主题中返回,“http://myHost/RED/..”将在红色主题中返回。如果用户更改主题,则 url 将更新。
上述方法的问题是下次用户浏览时,它将加载默认主题。
因此更好的方法是将主题保存为用户偏好的一部分。用户登录后从数据库读取主题并设置 RouteData 值。
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,
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.
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.
只需触摸 web.config。这是最简单、最可靠的方法。以编程方式刷新应用程序池是多余的。
如果您无法确定 web.config 在测试环境中的位置(因为
System.Web.HttpRequest.Current
为空,Server
也类似),您可以始终使用 app.config 文件来指出位置。再说一次,没有其他简单的方法可以做到这一点;即使像问题中提到的那样禁用输出缓存,也很难仅通过
web.config
来完成。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 (since
System.Web.HttpRequest.Current
is 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 through
web.config
alone.