.NET 4.5项目视图中Resx资源文件缓存问题求助
结合你描述的老.NET 4.5项目场景——用Resx+会话语言加载资源,唯独用户设置的两个视图切换语言后不生效,只有重启IIS管用——我整理了几个针对性的解决办法,亲测在类似场景里有效:
1. 给视图输出缓存加上语言维度的区分
问题大概率是IIS的输出缓存把这两个视图的HTML缓存死了,没有把会话里的语言作为缓存的区分依据。你可以给这两个视图加上自定义的输出缓存规则:
在userViewDetails.cshtml和userEditForm.cshtml的最顶部添加:
@OutputCache(Duration = 3600, VaryByCustom = "Language", Location = OutputCacheLocation.ServerAndClient)
然后在Global.asax里重写GetVaryByCustomString方法,让IIS识别“Language”这个自定义缓存维度:
public override string GetVaryByCustomString(HttpContext context, string custom) { if (custom.Equals("Language", StringComparison.OrdinalIgnoreCase)) { // 替换成你实际从会话模型获取语言的逻辑,比如Session["UserLang"] var currentLang = context.Session["CurrentLang"]?.ToString() ?? "en"; return currentLang; } return base.GetVaryByCustomString(context, custom); }
这样IIS会为不同语言生成独立的视图缓存,切换语言后自然能拿到对应版本的内容。
2. 绕过资源管理器的内置缓存加载资源
你之前调用ReleaseAllResources没效果,是因为共享项目里的ResourceManager是静态单例,这个方法并没有真正清除它的内部缓存。可以直接绕过内置缓存,手动实例化资源管理器读取:
把共享项目里的资源加载代码替换成:
// 替换成你共享项目的资源命名空间和资源类类型 var resourceAssembly = Assembly.GetAssembly(typeof(YourSharedResourceNamespace.Resources.English)); var rm = new ResourceManager($"YourSharedResourceNamespace.Resources.{lang}", resourceAssembly); // 用指定语言的CultureInfo加载,跳过默认缓存 string strLangResourceValue = rm.GetString(strLangResourceKey, new CultureInfo(lang));
这样每次获取资源都会直接读取Resx编译的资源文件,不会被全局缓存卡住。
3. 直接禁用这两个视图的服务器端缓存
如果上面的方法嫌麻烦,也可以直接禁用这两个视图的服务器端缓存,确保每次请求都重新渲染:
在视图顶部添加:
@OutputCache(NoStore = true, Location = OutputCacheLocation.None)
这个方法简单直接,虽然会损失一点缓存性能,但用户设置页面访问频率不高,完全可以接受。
4. 排除IIS静态内容缓存的干扰
有时候IIS会把Razor视图当成静态内容缓存,即使你设置了视图缓存规则也没用。可以在Web.config里针对这两个视图路径禁用静态缓存:
<location path="Views/User/userViewDetails.cshtml"> <system.webServer> <staticContent> <clientCache cacheControlMode="DisableCache" /> </staticContent> </system.webServer> </location> <location path="Views/User/userEditForm.cshtml"> <system.webServer> <staticContent> <clientCache cacheControlMode="DisableCache" /> </staticContent> </system.webServer> </location>
为什么之前手动清缓存没用?
你调用的HttpResponse.RemoveOutputCacheItem需要匹配视图的路由路径而非物理路径,所以可能路径写错了;而HttpContext.Cache.Remove只能清除应用程序级缓存,没法触及IIS的输出缓存或者ResourceManager的内部缓存,所以没效果。
内容的提问来源于stack exchange,提问作者Adrian

