Asp.Net 服务器端输出缓存在每次请求时都会被命中 (HttpHandler)

Asp.Net Server-side Output Cache gets hit every request (HttpHandler)

我在下面有一段非常简单的代码。

我尝试了几种方法,但我不明白为什么服务器端输出缓存在 http://localhost 时不工作。下面是 'cache settings' 的最后一次尝试,以便 不会 在调试输出窗格中看到 HIT。

快把我逼疯了!我该如何防止 HIT...?!当我打开开发人员工具并选中禁用缓存时,我期待缓存的服务器端副本,但在调试输出窗格中看不到 HIT。

我在 Windows 8,但即使在另一个 Windows 版本(/IIS 版本)上,我也无法想象最终的代码会有所不同。

using System;
using System.Diagnostics;
using System.Net.Http;
using System.Web;

namespace WebApplication1
{
    /// <summary>
    /// Summary description for MyHandler
    /// </summary>
    public class MyHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            Debug.WriteLine("HIT"+DateTime.Now.ToLongTimeString());

            context.Response.Cache.SetExpires(DateTime.Now.AddMinutes(5));
            context.Response.Cache.SetCacheability(HttpCacheability.Server);
            context.Response.Cache.SetValidUntilExpires(true);
            context.Response.Cache.SetOmitVaryStar(true);
            context.Response.Cache.VaryByParams["none"] = true;
            context.Response.Cache.SetMaxAge(new TimeSpan(0, 5, 0));

            // Just here for testing purposes
            const string url = "http://otherserver/image.png";
            using (var client = new HttpClient())
            {
                var task = client.GetStreamAsync(url);
                task.Wait();
                task.Result.CopyTo(context.Response.OutputStream);
                context.ApplicationInstance.CompleteRequest();
            }
        }

        public bool IsReusable
        {
            get { return true; }
        }
    }
}

原来是 ApplicationInstance.CompleteRequest() 造成了我的痛苦。根据MSDN它:

Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event.

这是Asp.Net pipeline flow

如您所见,处理程序正在中间某处执行,在调用 ApplicationInstance.CompleteRequest() 之后它会跳过所有内容并直接转到发送请求(或内部 CompleteRequest())。

发生这种情况时,它还会跳过 "Update cache" 事件。这是请求缓存更新的地方; Server-side 输出缓存项将添加到哪里...

所以,当您认为自己已经完成 HttpHandler 时,请注意 ApplicationInstance.CompleteRequest() 做了什么!

另一个有趣的读物:https://weblog.west-wind.com/posts/2009/May/21/Dont-use-ResponseEnd-with-OutputCache

快乐缓存!