Ignore url values with Outputcache
Asked Answered
M

1

1

When I use outputcaching on an action method it is cached by full url, what i would like to do is cache the page but ignore some parts of the url.

Custom route defined in Global.asax:

routes.MapRoute(
  "Template",
  "Report/{reportid}/{reportname}/Template/{templateid}/{action}",
  new { controller = "Template", action = "Index" }
);

My template controller

public class TemplateController : Controller
{
   [OutputCache(Duration=60*60*2)]
   public ActionResult Index(Template template)
   {
      /* some code */
   }
}

For example when I go to the following URL's:

http://mywebsite.com/Report/789/cacheme/Template/5
-> cached for 2 hours based on the url

http://mywebsite.com/Report/777/anothercacheme/Template/5
-> also gets cached for 2 hours based on that url

What I would like is that the OutputCache ignores the reportname and reportid values so when I go to the above url's it returns the same cached version. Is this possible with the OutputCache attribute or will I have to write my custom OutputCache FilterAttribute?

Mesnalty answered 14/4, 2011 at 8:11 Comment(2)
Perhaps, one of the way could be to make reportname, reportid as parameters your method and then use VaryByParam for templateid only. Apart from that custom filter attribute will be the way to go!Collodion
I tried it but it still does return different cached versions for the requested templateMesnalty
M
1

Ended up with the following (inspired by http://blog.stevensanderson.com/2008/10/15/partial-output-caching-in-aspnet-mvc/):

 public class ResultCacheAttribute : ActionFilterAttribute
    {
        public ResultCacheAttribute()
        {

        }

        public string CacheKey
        {
            get;
            private set;
        }

        public bool AddUserCacheKey { get; set; }
        public bool IgnoreReport { get; set; }

        /// <summary>
        /// Duration in seconds of the cached values before expiring.
        /// </summary>
        public int Duration
        {
            get;
            set;
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string url = "";
            foreach (var item in filterContext.RouteData.Values)
            {
                if (IgnoreReport)
                    if (item.Key == "reportid" || item.Key == "reportname")
                        continue;

                url += "." + item.Value;
            }
            if (AddUserCacheKey)
                url += "." + filterContext.HttpContext.User.Identity.Name;

            this.CacheKey = "ResultCache-" + url;

            if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
                this.CacheKey += "-ajax";

            if (filterContext.HttpContext.Cache[this.CacheKey] != null)
            {
                filterContext.Result = (ActionResult)filterContext.HttpContext.Cache[this.CacheKey];
            }
            else
            {
                base.OnActionExecuting(filterContext);
            }
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            filterContext.Controller.ViewData["CachedStamp"] = DateTime.Now;
            filterContext.HttpContext.Cache.Add(this.CacheKey, filterContext.Result, null, DateTime.Now.AddSeconds(Duration), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Default, null);

            base.OnActionExecuted(filterContext);
        }
    }
Mesnalty answered 18/4, 2011 at 8:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.