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
相关产品推荐
相关产品推荐

