Web API Core 3.1 ExceptionHandler 中间件在写入 HttpContext.Response 时抛出 'cannot write to closed stream'

Web API Core 3.1 ExceptionHandler middleware throws 'cannot write to closed stream' while writing to HttpContext.Response

我有一个简单的 Web API 核心 v3.1,我试图在其中处理全局异常。在遵循这个答案 之后,这是我的代码。

 app.UseExceptionHandler(appBuilder => appBuilder.Run(async context =>
 {
     var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
     var exception = exceptionHandlerPathFeature.Error;

     var result = JsonConvert.SerializeObject(new { error = exception.Message });
     context.Response.ContentType = "application/json";
     await context.Response.WriteAsync(result);
 }));

我在 context.Response.WriteAsync(result); 得到的错误是:

System.ObjectDisposedException: Cannot access a closed Stream.

我很确定我遗漏了一些基本的东西,但无法弄清楚。

我基本上需要在发生异常时将响应包装到一个对象中。

看来其他人(另一个中间件)已经关闭了流。

在 .net-core 中,顺序很重要。记得在你分享的 link 中:

Important: Remember to add it before UseMvc (or UseRouting in .Net Core 3) as order is important.

所以在任何其他 Middleware 和/或配置声明之前声明 UseExceptionHandler

Check the middleware guide here

Chain multiple request delegates together with Use. The next parameter represents the next delegate in the pipeline. You can short-circuit the pipeline by not calling the next parameter. You can typically perform actions both before and after the next delegate, as the following example demonstrates:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            // Do work that doesn't write to the Response.
            await next.Invoke();
            // Do logging or other work that doesn't write to the Response.
        });

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from 2nd delegate.");
        });
    }
}

UseExceptionHandler is the first middleware component added to the pipeline. Therefore, the Exception Handler Middleware catches any exceptions that occur in later calls.

第一个 运行 终止管道。所以你可以做一些工作,但最后当第一个 运行 发生时,响应将关闭。

请分享更多代码,以便我们提供更多帮助。