.NET Core中间件被调用两次且返回500错误的求助
问题:自定义中间件被重复调用且第二次返回500状态码
我在.NET Core中实现了一个中间件,用于读取POST请求体并验证是否包含重复的name属性。目前遇到两个问题:一是该中间件会被调用两次,二是第二次调用时返回500状态码。我仅在Startup.cs中添加了一次该中间件,尝试多种方法均无法解决,恳请协助。
中间件代码
public async Task InvokeAsync(HttpContext context) { var request = context.Request; if (request.Method != HttpMethods.Post) { await _next(context); return; } var requestBody = await ReadRequestBody(request); if (Validation(requestBody)) { context.Response.StatusCode = StatusCodes.Status400BadRequest; await context.Response.WriteAsync("Duplicated fields"); return; } request.Body = new MemoryStream(Encoding.UTF8.GetBytes(requestBody)); await _next(context); return; }
Startup.cs配置代码
public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseMiddleware<SingleOccurrenceMiddleware>(); if (env.EnvironmentName != "Local") app.UseHsts(); app.UseXRay("UKIAwardsCampaigns"); app.UseHttpsRedirection(); app.UseRouting(); #region NetCore 3.1 Middlewares migration //Setup Cors from EnvironmentVar app.UseCorsFromEnvironmentVar("ASPNETCORE_CORS_URLs"); app.UseAuthentication(); //Add a middleware to build a EnterpriseIdentity from a claims Identity app.UseEnterpriseIdentity(); app.UseAuthorization(); #endregion app.UseLocalization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
问题原因及解决办法
1. 请求体流读取不当导致的500错误
你的中间件在读取请求体后,通过重新创建MemoryStream替换原始请求体,这种方式可能导致后续流程中流状态异常(比如原始流被关闭),第二次调用时无法正常读取请求体引发500错误。
修复方法:
启用请求体缓冲功能,读取后重置流位置,而非替换流:
public async Task InvokeAsync(HttpContext context) { var request = context.Request; if (request.Method != HttpMethods.Post) { await _next(context); return; } // 启用缓冲,允许重复读取请求体 request.EnableBuffering(); var requestBody = await ReadRequestBody(request); // 重置流位置,让后续中间件/模型绑定正常读取 request.Body.Position = 0; if (Validation(requestBody)) { context.Response.StatusCode = StatusCodes.Status400BadRequest; await context.Response.WriteAsync("Duplicated fields"); return; } await _next(context); return; } // 确保ReadRequestBody不会关闭原始流 private async Task<string> ReadRequestBody(HttpRequest request) { using var reader = new StreamReader(request.Body, Encoding.UTF8, leaveOpen: true); return await reader.ReadToEndAsync(); }
2. HttpsRedirection引发的二次调用
你的中间件放在UseHttpsRedirection之前,如果客户端通过HTTP发送POST请求,UseHttpsRedirection会返回307重定向(保留请求方法和体)到HTTPS,客户端会发起第二次HTTPS的POST请求,导致中间件被调用两次。
修复方法:
调整中间件顺序,将自定义中间件移到UseHttpsRedirection之后,只处理HTTPS请求:
public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.EnvironmentName != "Local") app.UseHsts(); app.UseXRay("UKIAwardsCampaigns"); app.UseHttpsRedirection(); // 将自定义中间件移到HTTPS重定向之后 app.UseMiddleware<SingleOccurrenceMiddleware>(); app.UseRouting(); #region NetCore 3.1 Middlewares migration //Setup Cors from EnvironmentVar app.UseCorsFromEnvironmentVar("ASPNETCORE_CORS_URLs"); app.UseAuthentication(); //Add a middleware to build a EnterpriseIdentity from a claims Identity app.UseEnterpriseIdentity(); app.UseAuthorization(); #endregion app.UseLocalization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
3. 排查500错误细节
如果以上调整后仍有500错误,查看服务器日志获取具体异常信息,通常是请求体读取相关的IO异常,按照上述流处理方式即可解决。
内容的提问来源于stack exchange,提问作者Kenzo_Gilead
相关产品推荐
相关产品推荐

