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

ASP.NET Core异常中间件在.NET 5中返回404 JSON响应失败的解决方法

解决.NET5中ExceptionHandler中间件返回404 JSON响应失败的问题

这个问题我之前升级.NET5的时候也碰到过!根源在于.NET5对404状态码的处理逻辑做了调整,默认会触发请求重新执行的机制,干扰了你在异常处理中间件里的响应写入操作。

问题原因

在.NET5及后续版本中,当你把响应状态码设为404时,ASP.NET Core会自动添加IStatusCodeReExecuteFeature到请求特性集合中。这个特性会让框架尝试重新执行请求,去查找是否有匹配的端点或者静态资源。这就导致你还在写入JSON响应的时候,响应流被提前关闭了,所以HttpClient会抛出"Error while copying content to a stream"的错误。而像400这类状态码不会触发这个重新执行逻辑,所以能正常返回。

解决方案

方法一:清除状态码重执行特性(针对性解决自定义异常场景)

在你的异常处理中间件中,设置完404状态码后,移除IStatusCodeReExecuteFeature,阻止框架后续的自动处理逻辑,同时显式设置响应的Content-Type确保客户端识别为JSON:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseExceptionHandler(appBuilder =>
    {
        appBuilder.Run(async context =>
        {
            // 清除状态码重执行特性,阻止框架自动处理404
            var statusCodeFeature = context.Features.Get<IStatusCodeReExecuteFeature>();
            if (statusCodeFeature != null)
            {
                context.Features.Set<IStatusCodeReExecuteFeature>(null);
            }

            context.Response.StatusCode = (int)HttpStatusCode.NotFound;
            // 显式设置Content-Type为JSON格式
            context.Response.ContentType = "application/json";
            
            var responseContent = new { StatusCode = context.Response.StatusCode, Message = "Not found" };
            await context.Response.WriteAsJsonAsync(responseContent);
        });
    });

    // 其他中间件配置(路由、端点等)
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

方法二:使用自定义状态码页面中间件(通用404处理)

如果你的应用需要统一处理所有404场景(包括未找到端点的情况,不只是自定义异常),可以结合UseExceptionHandler和UseStatusCodePages中间件,分工处理异常捕获和状态码响应:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // 先捕获自定义异常并设置对应的状态码
    app.UseExceptionHandler(appBuilder =>
    {
        appBuilder.Run(async context =>
        {
            var exceptionFeature = context.Features.Get<IExceptionHandlerPathFeature>();
            if (exceptionFeature?.Error is NotFoundException)
            {
                context.Response.StatusCode = (int)HttpStatusCode.NotFound;
            }
            // 可添加其他异常的状态码映射逻辑
        });
    });

    // 统一处理所有404响应,返回JSON格式内容
    app.UseStatusCodePages(async context =>
    {
        if (context.HttpContext.Response.StatusCode == (int)HttpStatusCode.NotFound)
        {
            context.HttpContext.Response.ContentType = "application/json";
            var responseContent = new { StatusCode = 404, Message = "Not found" };
            await context.HttpContext.Response.WriteAsJsonAsync(responseContent);
        }
        // 可添加其他状态码的响应逻辑
    });

    // 其他中间件配置
    app.UseRouting();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

注意事项

  • 方法一更贴合你的场景,直接在异常处理中间件内部解决了404响应被干扰的问题,确保自定义NotFoundException被正确处理为JSON格式的404响应。
  • 一定要显式设置ContentType为application/json,避免客户端无法正确解析响应内容。

内容的提问来源于stack exchange,提问作者Nick Prince

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 13:57:50