OutputCache and RenderAction Cache Landing Page

I have a ViewPage that contains <% Html.RenderAction<MyController>(c => c.SidebarStats()); %> <% Html.RenderAction<MyController>(c => c.SidebarStats()); %> . On the controller action for the SidebarStats action, I have an OutputCache action filter to cache only that part of the page. However, the entire page receives caching, not just this action.

I remember seeing somewhere that this might be a bug with ASP.NET MVC, although I'm not sure. I am currently using ASP.NET MVC RC1, IIS7, Windows Server 2008 and .NET 3.5 SP1.

+7
caching asp.net-mvc
source share
3 answers

I wrote a solution to this problem here . It is simple, but only works if you use WebFormViewEngine. We will carefully study what is required to make this work for all viewing mechanisms.

+10
source share

According to Microsoft, this is a known bug without a known fix. Only workarounds are suggested to create your own OutputCache action filter.

+2
source share

Now I use what Steve Sanderson has done on his blog , and this is very nice:

 public class ActionOutputCacheAttribute : ActionFilterAttribute { // This hack is optional; I'll explain it later in the blog post private static readonly MethodInfo _switchWriterMethod = typeof (HttpResponse).GetMethod("SwitchWriter", BindingFlags.Instance | BindingFlags.NonPublic); private readonly int _cacheDuration; private string _cacheKey; private TextWriter _originalWriter; public ActionOutputCacheAttribute(int cacheDuration) { _cacheDuration = cacheDuration; } public override void OnActionExecuting(ActionExecutingContext filterContext) { _cacheKey = ComputeCacheKey(filterContext); var cachedOutput = (string) filterContext.HttpContext.Cache[_cacheKey]; if (cachedOutput != null) filterContext.Result = new ContentResult {Content = cachedOutput}; else _originalWriter = (TextWriter) _switchWriterMethod.Invoke(HttpContext.Current.Response, new object[] {new HtmlTextWriter(new StringWriter())}); } public override void OnResultExecuted(ResultExecutedContext filterContext) { if (_originalWriter != null) // Must complete the caching { var cacheWriter = (HtmlTextWriter) _switchWriterMethod.Invoke(HttpContext.Current.Response, new object[] {_originalWriter}); string textWritten = (cacheWriter.InnerWriter).ToString(); filterContext.HttpContext.Response.Write(textWritten); filterContext.HttpContext.Cache.Add(_cacheKey, textWritten, null, DateTime.Now.AddSeconds(_cacheDuration), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); } } private string ComputeCacheKey(ActionExecutingContext filterContext) { var keyBuilder = new StringBuilder(); foreach (var pair in filterContext.RouteData.Values) keyBuilder.AppendFormat("rd{0}_{1}_", pair.Key.GetHashCode(), pair.Value.GetHashCode()); foreach (var pair in filterContext.ActionParameters) keyBuilder.AppendFormat("ap{0}_{1}_", pair.Key.GetHashCode(), pair.Value.GetHashCode()); return keyBuilder.ToString(); } } 

For more information, visit Steve Sanderson's blog article .

0
source share

All Articles