ASP.NET中用Attribute加密API响应时遇Content-Length不匹配错误
问题原因分析
出现Response Content-Length mismatch错误的核心原因有三点:
- 异步方法错误使用
async void:OnResultExecuted作为过滤器的异步生命周期方法,用async void会导致ASP.NET无法跟踪异步操作完成状态,引发响应处理混乱。 - 未更新响应头:原始响应已经生成了
Content-Length头,替换加密内容后长度和原始值不匹配,触发校验错误。 - 流处理不规范:未保存并恢复原始响应流,也未重置响应流位置,导致内容读取或写入异常。
修复后的过滤器代码
public class MyCustomFilter : ActionFilterAttribute { private MemoryStream _responseStream; private Stream _originalResponseBody; public override void OnActionExecuting(ActionExecutingContext context) { // 保存原始响应流,避免资源泄漏 _originalResponseBody = context.HttpContext.Response.Body; // 创建内存流捕获原始响应内容 _responseStream = new MemoryStream(); context.HttpContext.Response.Body = _responseStream; } public override async Task OnResultExecutedAsync(ResultExecutedContext context, CancellationToken cancellationToken) { // 重置内存流到起始位置,确保能读取完整原始内容 _responseStream.Seek(0, SeekOrigin.Begin); using (var reader = new StreamReader(_responseStream)) { var originalContent = await reader.ReadToEndAsync(cancellationToken); // 执行加密操作 var encryptedContent = AesOperation.EncryptString("b14ca5898a4e4133bbce2ea2315a1916", originalContent); // 清除原始响应头,避免Content-Length不匹配 context.HttpContext.Response.ClearHeaders(); // 设置加密内容的类型 context.HttpContext.Response.ContentType = "text/plain"; // 写入加密后的响应内容 await context.HttpContext.Response.WriteAsync(encryptedContent, cancellationToken); } // 恢复原始响应流并清理内存流 context.HttpContext.Response.Body = _originalResponseBody; _responseStream.Dispose(); await base.OnResultExecutedAsync(context, cancellationToken); } }
关键修改说明
- 替换
async void为async Task的OnResultExecutedAsync:这是ASP.NET Core过滤器异步方法的标准写法,确保框架能正确等待异步操作完成。 - 保存并恢复原始响应流:避免流资源泄漏,保证后续响应处理流程正常。
- 调用
ClearHeaders():清除原始响应生成的Content-Length等头信息,避免新内容长度和原始头值不匹配。 - 传递
CancellationToken:符合异步编程最佳实践,支持请求取消场景。
内容的提问来源于stack exchange,提问作者SinaMN75
相关产品推荐
相关产品推荐

