在使用dynamicCompressionBeforeCache缓存之前重写asp.net响应

时间:2011-09-09 15:08:58

标签: asp.net

我的ASP.NET库安装了一个响应过滤器来解析和更改页面的HTML输出。这是有效的,直到在web.config中启用以下内容:

<system.webServer>
    <urlCompression doDynamicCompression="true" dynamicCompressionBeforeCache="true" />
</system.webServer>

我的响应过滤器仍然被调用,但传递的似乎是压缩数据,而不是原始HTML。

如何在页面存储到输出缓存之前确保重写?

将dynamicCompressionBeforeCache设置为false不是一个选项,因为此库旨在用于其他人可能有充分理由启用压缩的Web应用程序。

2 个答案:

答案 0 :(得分:5)

alexb的回答帮助我找到了解决方案。

关键是意识到我的响应过滤器在IIS DynamicCompressionModule之后运行。这可以通过在请求处理程序执行后立即刷新响应来强制过滤器运行来修复。

public class MyModule : IHttpModule
{
    public void Init(HttpApplication application)
    {
        application.BeginRequest += application_BeginRequest;
        application.PostRequestHandlerExecute += application_PostRequestHandlerExecute;
    }

    void application_BeginRequest(object sender, EventArgs e)
    {
        // Install response filter
        var response = ((HttpApplication)sender).Context.Response;
        response.Filter = new RewritingFilter(response.Filter);
    }

    void application_PostRequestHandlerExecute(object sender, EventArgs e)
    {
        // Flush immediately after the request handler has finished.
        // This is Before the output cache compression happens.
        var response = ((HttpApplication)sender).Context.Response;
        response.Flush();
    }

    public void Dispose()
    {
    }
}

答案 1 :(得分:3)

根据this blog post,负责处理动态压缩的DynamicCompressionModule在ReleaseRequestState阶段(在UpdateRequestCache阶段之前,当页面存储到输出缓存时)运行。因此:

  • 如果要在执行动态压缩之前处理响应,则应将过滤代码放在连接到PostRequestHandlerExecute事件的HttpModule中;
  • 如果要处理响应缓存已执行,但在压缩之后,则应将过滤代码放在一个挂起PostReleaseRequestState事件的HttpModule中。

以下是如何执行此操作的示例:

public class SampleModule : IHttpModule
{
    public void Dispose()
    {
        return;
    }

    public void Init(HttpApplication context)
    {
        context.PostRequestHandlerExecute += new EventHandler(App_OnPostRequestHandlerExecute);
        context.PostReleaseRequestState += new EventHandler(App_OnPostReleaseRequestState);
    }

    private void App_OnPostRequestHandlerExecute(object sender, EventArgs e)
    {
        HttpApplication app = (HttpApplication)sender;
        HttpResponse response = app.Context.Response;

        response.Write("<b>Modified!</b>");
    }

    private void App_OnPostReleaseRequestState(object sender, EventArgs e)
    {
        HttpApplication app = (HttpApplication)sender;
        HttpResponse response = app.Context.Response;

        //check if the output has been compressed - make sure to actually test if for whatever content encoding you want to deal with
        if (response.Headers["Content-Encoding"] != null)
        {
            //do stuff
        }
        else
        {
            //do some other stuff
        }
    }
}

然后使用web.config文件注册您的模块:

<add name="SampleModule" type="My.ModuleNamespace.SampleModule" />