You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ninject与Gzip响应压缩冲突导致乱码问题求助

问题

使用自定义CompressAttribute对Web API响应做压缩,加入Ninject后压缩失效,返回乱码内容:

h=d  ݛMo 6    ΂ߢxl C)
xoE W  cW6  }IQ    fb B `I "  ;3 |+N   ) ߊ   ևۦ0dE      i  >    ~jv   闯    Ԭ   R{l  

自定义压缩属性代码:

using System.IO.Compression;

public class CompressAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var encodingsAccepted = filterContext.HttpContext.Request.Headers["Accept-Encoding"];
        if (string.IsNullOrEmpty(encodingsAccepted)) return;

        encodingsAccepted = encodingsAccepted.ToLowerInvariant();
        var response = filterContext.HttpContext.Response;

        if (encodingsAccepted.Contains("deflate"))
        {
            response.AppendHeader("Content-encoding", "deflate");
            response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
        }
        else if (encodingsAccepted.Contains("gzip"))
        {
            response.AppendHeader("Content-encoding", "gzip");
            response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
        }
    }
}
解决方案

问题根源是Ninject的请求生命周期管理与ActionFilterAttribute的执行时机冲突,导致响应流被异常处理,可通过以下方式修复:

1. 调整过滤器执行时机到OnActionExecuted

将压缩逻辑移到OnActionExecuted,确保响应内容生成后再处理压缩,避免Ninject中间件干扰流操作:

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    var encodingsAccepted = filterContext.HttpContext.Request.Headers["Accept-Encoding"];
    if (string.IsNullOrEmpty(encodingsAccepted)) return;

    encodingsAccepted = encodingsAccepted.ToLowerInvariant();
    var response = filterContext.HttpContext.Response;

    // 防止重复压缩
    if (response.Headers.AllKeys.Contains("Content-encoding")) return;

    if (encodingsAccepted.Contains("deflate"))
    {
        response.AppendHeader("Content-encoding", "deflate");
        response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
    }
    else if (encodingsAccepted.Contains("gzip"))
    {
        response.AppendHeader("Content-encoding", "gzip");
        response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
    }
}

2. 配置Ninject保留原生过滤器执行顺序

若必须使用OnActionExecuting,在Ninject配置中明确绑定压缩过滤器的优先级,确保其优先于Ninject拦截器执行:

// 在NinjectWebCommon.cs的RegisterServices方法中添加
private static void RegisterServices(IKernel kernel)
{
    // 其他服务注册...
    kernel.BindHttpFilter<CompressAttribute>(FilterScope.Action).WhenControllerHas<CompressAttribute>();
}

3. 确保压缩流正确收尾

部分场景下,压缩流未被正确flush或关闭会导致乱码,可在OnResultExecuted中处理流的关闭:

public override void OnResultExecuted(ResultExecutedContext filterContext)
{
    var response = filterContext.HttpContext.Response;
    var compressStream = response.Filter as DeflateStream ?? response.Filter as GZipStream;
    compressStream?.Close();
    base.OnResultExecuted(filterContext);
}

内容的提问来源于stack exchange,提问作者shahab javanmardi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 00:15:14