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

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:15:42