如何在ASP.NET MVC中为经过身份验证的用户关闭输出缓存?

Jak*_*urc 15 asp.net-mvc outputcache

我有一个ASP.NET MVC应用程序.我需要缓存一些页面,但仅限于未经过身份验证的用户.

我尝试使用VaryByCustom="user"以下GetVaryByCustomString实现:

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);
}
Run Code Online (Sandbox Code Playgroud)

然而,这并不是我需要的,因为页面仍然被缓存.唯一的区别是现在分别为每个用户缓存.

一种可能的解决方案是Guid.NewGuid()每次用户进行身份验证时返回,但这对我来说似乎是一种巨大的资源浪费.

所以你有什么提示吗?

Jak*_*urc 32

所以这就是我所做的:

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;          
    }
}
Run Code Online (Sandbox Code Playgroud)

非常感谢Craig Stuntz向我指出正确的方向,我的答案在不知不觉中被低估了.

  • -1.这不行.一旦该逻辑针对经过身份验证的请求执行,*所有*连续请求将不具有缓存.请记住,该属性是跨所有HttpApplication实例在AppDomain生命周期内存在的单个实例.要从每个请求的FilterAttribute更改缓存行为,您必须重新实现base.OnResultExecuting中的逻辑,以向Page.InitOutputCache提供单独的实例.查看来源. (3认同)
  • 它适用于Pages,但不幸的是**不适用于部分视图** (2认同)

Fel*_*oto 12

通常会对属性进行缓存,然后您需要存储原始位置.如果您访问Logged页面,它将Location设置为None,然后当您以匿名方式访问时,它仍然是None.

public class AuthenticatedOnServerCacheAttribute : OutputCacheAttribute
{
    private OutputCacheLocation? originalLocation;

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        var httpContext = filterContext.HttpContext;

        if (httpContext.User.Identity.IsAuthenticated)
        {
            originalLocation = originalLocation ?? Location;
            Location = OutputCacheLocation.None;
        }
        else
        {
            Location = originalLocation ?? Location;
        }

        base.OnResultExecuting(filterContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案.Jakub的答案是行不通的 (2认同)