ASP.NET中的条件输出缓存

时间:2011-01-29 14:43:29

标签: asp.net caching outputcache

我有一个关于如何以编程方式指示ASP.NET跳过从输出缓存中解析请求的问题。

想象一下,您通过在运行时将缓存策略设置从CMS应用到HttpResponse来缓存页面输出(例如http://domain/page.aspx)。在每个请求的基础上取决于即当前用户是否经过身份验证+一组已知组的成员(或由业务逻辑匹配),我想指示ASP.NET 跳过解析来自输出缓存的请求。

场景是两个不同的用户同时(或更多)在系统上。用户A经过身份验证+一组已知组的成员,用户B是匿名用户。无论缓存的页面是什么,我都希望经过身份验证的用户浏览所有页面,就像没有启用输出缓存一样 - 永远;同时,我希望ASP.NET继续为匿名用户(或者与业务逻辑不匹配的用户)提供输出缓存页面。

典型的建议是使用VaryByHeader,VaryByParam等并污染输出缓存 - 不好,但是在使用Reflector挖掘输出缓存模块时,我注意到输出缓存模块跳过当前请求,以防几个存在已知的“缓存控制”头部。至于我关注标题,如果用户强制通过在地址栏中点击F5或ENTER来呈现新的副本,则会从浏览器发送这些标题。

所以,我正在做的只是在输出缓存订阅的ResolveRequestCache事件之前的事件中,在自定义http模块中将“cache-control”标头设置为“no-cache”。像这样:

context.Request.Headers["Cache-Control"] = "no-cache";

一切都很好,但是,如果设置了HttpCachePolicy.SetValidUntilExpires(true)缓存策略,ASP.NET将忽略先前设置的请求标头并从输出缓存中提供请求。

作为替代方案,我想我可以在同一个http模块中的后处理事件中编写其他代码,以确保调用HttpCachePolicy.SetValidUntilExpires(false),以防配置输出缓存,但我认为它会是一个更干净的解决方案,实际上能够指示ASP.NET简单地跳过从输出缓存中解析请求。我可以想象这个问题有很多尴尬的解决方案,但我追求的是正确的。

作为参考,我一直在尝试HttpCachePolicy类的大多数相关方法,例如:

HttpResponse.Cache.SetNoServerCaching()).

2 个答案:

答案 0 :(得分:3)

您可以在应用程序中添加HttpCacheValidateHandler,您可以在其中实现所需的任何逻辑。它将在ResolveRequestCache事件期间执行,该事件在执行身份验证和授权后触发。关键是在您要绕过缓存的情况下返回HttpValidationStatus.IgnoreThisRequest

请参阅此示例HttpModule以供参考:

public class CacheModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest +=
            (s, e) => context.Context.Response.Cache
                        .AddValidationCallback(CacheHandler, null);
    }

    private static void CacheHandler(
        HttpContext context, object data,
        ref HttpValidationStatus validationstatus)
    {
        // bypass cache for all users with skipCache cookie
        validationstatus =
            context.Request.Cookies["skipCache"] != null
                ? HttpValidationStatus.IgnoreThisRequest
                : HttpValidationStatus.Valid;
    }

    public void Dispose()
    {
    }
}

答案 1 :(得分:0)

我不确定在缓存某些内容后是否支持这样做的方法。

但是你为什么不喜欢VaryByHeader选项呢?假设有一个标题,您可以查看以区分已登录和未登录的用户,这应该有效。如果您有逻辑仅在用户未登录时填充输出缓存,则不会污染缓存。登录用户总是会遇到缓存未命中。