【问题标题】:Conditional output caching in ASP.NETASP.NET 中的条件输出缓存
【发布时间】:2011-06-17 18:30:44
【问题描述】:

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

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

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

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

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

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

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

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

作为参考,我一直在尝试 HttpCachePolicy 类的大部分相关方法(如果不是全部),例如:

HttpResponse.Cache.SetNoServerCaching()).

【问题讨论】:

    标签: asp.net caching outputcache


    【解决方案1】:

    您可以将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()
        {
        }
    }
    

    【讨论】:

    • 奥利弗,永远不会太晚,感谢我现在实施的答案。我想知道我怎么会错过 AddValidationCallback 方法.. 再说一次,重要的是使用框架,这是我在之前的实现中错过的。
    【解决方案2】:

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

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

    【讨论】:

    • VaryByHeader 绝对可以工作,但我需要一种机制来确保设置标题。你在暗示什么?实现一个设置自定义标头的 HttpModule (即 Headers["custom-header"] = "no-cache" ,然后改变?
    • 也许我没有完全考虑清楚。我希望有来自浏览器的不同标头(例如身份验证 cookie)可以区分这两种情况。
    • 这是一个很好的建议,但我所拥有的只是表单身份验证或类似基于 cookie 的身份验证的实际签名。但是,由于存在不同类型的授权级别,所有这些都是从相同的身份验证机制(即 cookie)解决的,我可以根据授权级别来设置不同的 cookie。我认为这听起来很复杂,就像是在针对框架工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    相关资源
    最近更新 更多