如何在ASP.NET MVC中用OutputCache覆盖BaseController的NoCacheAttribute
如何用OutputCache覆盖BaseController上的NoCacheAttribute
这个问题我之前也碰到过,核心矛盾在于:控制器级的NoCacheAttribute会和方法级的OutputCacheAttribute同时执行,最终NoCache的缓存头设置会覆盖掉OutputCache的配置。要解决这个问题,我们只需要让自定义的NoCacheAttribute具备“检测并避让”的逻辑即可。
方案一:修改NoCacheAttribute,自动检测OutputCache
直接修改你的NoCacheAttribute,在执行缓存头设置前,检查当前Action是否标记了OutputCacheAttribute。如果存在,就跳过NoCache的逻辑,让OutputCache的设置生效。
代码示例:
public class NoCacheAttribute : ActionFilterAttribute { public override void OnResultExecuting(ResultExecutingContext filterContext) { // 检查当前Action(包括方法和控制器层级)是否有OutputCacheAttribute var hasOutputCache = filterContext.ActionDescriptor .GetCustomAttributes(typeof(OutputCacheAttribute), inherit: true) .Any(); if (hasOutputCache) { // 存在OutputCache,跳过NoCache的处理逻辑 base.OnResultExecuting(filterContext); return; } // 原有的NoCache逻辑 filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); filterContext.HttpContext.Response.Cache.SetNoStore(); filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1)); base.OnResultExecuting(filterContext); } }
这样修改后,只要你的控制器方法上标记了[OutputCache(...)],NoCacheAttribute就会自动“让路”,不会再设置禁止缓存的响应头。
方案二:手动标记跳过NoCache(可选)
如果你希望更灵活地控制——比如某些方法不需要OutputCache但也想跳过NoCache——可以给NoCacheAttribute加一个开关属性:
public class NoCacheAttribute : ActionFilterAttribute { // 添加一个开关,默认开启NoCache逻辑 public bool Skip { get; set; } = false; public override void OnResultExecuting(ResultExecutingContext filterContext) { // 先检查方法级的NoCache是否设置了Skip=true var methodNoCache = filterContext.ActionDescriptor .GetCustomAttributes(typeof(NoCacheAttribute), inherit: false) .FirstOrDefault() as NoCacheAttribute; // 检查是否需要跳过:要么方法标记了Skip,要么存在OutputCache bool shouldSkip = methodNoCache?.Skip == true || filterContext.ActionDescriptor .GetCustomAttributes(typeof(OutputCacheAttribute), inherit: true) .Any(); if (shouldSkip) { base.OnResultExecuting(filterContext); return; } // 原有的NoCache逻辑 filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); filterContext.HttpContext.Response.Cache.SetNoStore(); filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1)); base.OnResultExecuting(filterContext); } }
然后在需要用OutputCache的方法上,这样标记:
[OutputCache(Duration = 3600, VaryByParam = "none")] [NoCache(Skip = true)] public ActionResult CachedData() { // 你的业务逻辑 return View(); }
为什么直接加OutputCache没用?
ASP.NET MVC中,控制器级过滤器和方法级过滤器都会执行,两者都会修改响应缓存头。默认情况下NoCache设置的NoCache、NoStore会覆盖OutputCache的缓存策略,所以必须让NoCache主动跳过逻辑,才能让OutputCache的配置生效。
内容的提问来源于stack exchange,提问作者user1955255
相关产品推荐
相关产品推荐

