views:

272

answers:

1

I have an ASP.NET MVC application. I need to cache some actions (pages) however for some pages I need do such only for non authenticated users.

I've tried to user VaryByCustom="user" with following GetVaryByCustomString implementation.

public override string GetVaryByCustomString(HttpContext context, string custom)
{
  if (custom == "user")
  {
      if (context.User.Identity.IsAuthenticated)
      {
        return context.User.Identity.Name;
      }
      else
      {
        return "";
      }
  }  

  return base.GetVaryByCustomString(context, custom);
}

However this isn't exactly what I need because pages are still cached. Only difference is that now is cached for each user separately.

One possible solution is to return Guid.NewGuid() each time when user is Authenticated, but I looks like huge waste of resources to me.

So do you have any tips for me?

+7  A: 

So here is what I done:

public class NonAuthenticatedOnlyCacheAttribute : OutputCacheAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
      var httpContext = filterContext.HttpContext;

      if (httpContext.User.Identity.IsAuthenticated)
      {
        // it's crucial not to cache Authenticated content
        Location = OutputCacheLocation.None;
      }

      // this smells a little but it works
      httpContext.Response.Cache.AddValidationCallback(IgnoreAuthenticated, null);

      base.OnResultExecuting(filterContext);
    }

    // This method is called each time when cached page is going to be
    // served and ensures that cache is ignored for authenticated users.
    private void IgnoreAuthenticated(HttpContext context, object data, ref HttpValidationStatus validationStatus)
    {
      if (context.User.Identity.IsAuthenticated)            
        validationStatus = HttpValidationStatus.IgnoreThisRequest;          
      else          
        validationStatus = HttpValidationStatus.Valid;          
    }
}

Many thanks to Craig Stuntz who pointed me to correct direction and whose answer I unwittingly downvoted.

Jakub Šturc
Cool! Nice solution.
Nathan Taylor