IAsyncActionFilter的OnActionExecutionAsync偶发不触发 带IFormFile请求超时求助
根本原因
- 你当前使用的
IAsyncActionFilter执行时机在模型绑定完成之后。当请求为携带文件的multipart/form-data类型时,ASP.NET Core 模型绑定器需要完整读取、解析整个请求体(包括上传的文件内容),才会进入Action过滤器的执行逻辑。 - 你遇到的过滤器不执行、请求超时问题,本质是请求卡在了模型绑定解析multipart请求体的阶段,根本没有走到过滤器的执行环节,因此过滤器开头的断点不会命中。
- 偶发的原因通常是两类:要么是自定义中间件提前读取了请求体且未重置读取位置,导致模型绑定阶段无法正常读取请求体陷入等待;要么是客户端偶发未正确传递
multipart/form-data的边界标识,导致服务端解析请求体时阻塞直到超时。
解决方案
最优方案:调整授权过滤器类型
将授权逻辑从IAsyncActionFilter迁移到IAsyncAuthorizationFilter(授权过滤器):
- 授权过滤器的执行时机远早于模型绑定,仅需要请求头加载完成即可执行,不需要等待请求体解析,直接就能读取
ApiKey请求头完成校验,校验失败直接返回401,既解决了当前阻塞问题,也避免了未授权请求占用服务器带宽上传大文件的问题。
改造后的过滤器示例代码:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class ApiKeyAuthAttribute: Attribute, IAsyncAuthorizationFilter { private const string ApiKeyHeadername = "ApiKey"; public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { DataAcces dataAcces = context.HttpContext.RequestServices.GetService(typeof(DataAcces)) as DataAcces; if (!context.HttpContext.Request.Headers.TryGetValue(ApiKeyHeadername, out var apiKey) || !dataAcces.TryAuthenticate(apiKey, out NsInvoiceRecognitionCredentials credentials)) { context.Result = new UnauthorizedResult(); return; } // 存入HttpContext.Items避免强转控制器,适配多控制器复用场景 context.HttpContext.Items["Credentials"] = credentials; } }
控制器中取Credentials的逻辑调整为:
var credentials = HttpContext.Items["Credentials"] as NsInvoiceRecognitionCredentials;
备选方案:修复模型绑定阻塞问题
如果需要保留ActionFilter的实现,按以下步骤排查修复:
- 配置表单解析参数,避免默认限制导致的解析阻塞,在Program.cs中添加如下配置:
builder.Services.Configure<Microsoft.AspNetCore.Http.Features.FormOptions>(options => { // 根据业务需要调整最大上传大小,默认值为128MB options.MultipartBodyLengthLimit = 20 * 1024 * 1024; // 开启请求体缓冲,允许重复读取 options.BufferBody = true; });
- 检查所有自定义中间件,确认如果有读取
Request.Body的逻辑,读取完成后必须调用context.Request.Body.Position = 0重置读取位置,否则后续模型绑定阶段无法正常读取请求体。 - 校验客户端请求,确保所有携带文件的请求都正确传递了包含boundary标识的
Content-Type请求头,格式参考:Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW。
内容的提问来源于stack exchange,提问作者Wessel Ottevanger
相关产品推荐
相关产品推荐

