未传递自定义中间件异常处理程序响应内容

Custom middleware exception handler response content not passed

我在使用 ASP.Net 核心自定义中间件时遇到了一个奇怪的问题。

我有一个异常处理程序,我正在尝试记录异常,然后向调用者发送一条通用消息,但不包含似乎默认发送的异常详细信息。

问题是发送的响应没有正文。

我的代码:

public async Task Invoke(HttpContext context)
{
    try
    {
        await next.Invoke(context);
    }
    catch (Exception e)
    {
        logger.LogError(e, "Request threw an exception");

        context.Response.StatusCode = 500;

        using (var writer = new StreamWriter(context.Response.Body))
        {
            await writer.WriteAsync($"Error on server processing request");
            await writer.FlushAsync();
        }
    }
}

我正在使用 .Net 5。这个项目是一个 Web API 项目,以防有任何不同。

我正在通过 swagger UI 调用我的 API 并且我还在使用 Edge(Chromium 版本)中的开发工具检查响应以确保 swagger 没有隐藏正文。

似乎没有响应主体,它只是一个带有 500 代码的空响应。

调试器中的

运行 显示它正在执行代码,如果我将响应代码更改为 566,则 SwaggerUI 收到响应代码,因此它正在执行某些操作。

注意:在我添加 FlushAsync() 调用之前,我收到了一个发送给 Swagger 的异常,说在刷新时处理正在使用同步写入,所以这似乎是必要的。

更新: 管道配置,按要求:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment() || env.IsTesting())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Clients v1"));
    }

    app.UseRequestLoggingMiddleware(); // My custom middleware

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

无论环境如何(开发、测试、暂存或生产),行为都是相同的

我不确定为什么使用 context.Response.Body 不起作用,但我所做的是直接在 context.Response:

上使用这些方法
context.Response.StatusCode = 500;
await context.Response.WriteAsync($"Error on server processing request");

更新: 鉴于您的中间件管道以 app.UseDeveloperExceptionPage() 开头,我怀疑这就是覆盖响应的原因 - 至少如果您是 运行 开发或测试作为环境。这是一个中间件,它实际上公开了您所说的要避免的完整异常详细信息。在 ASP.NET 核心项目 boilerplate/template 中,只有当生产环境中没有 运行 时才故意添加。

因此,通过将 ASPNETCORE_ENVIRONMENT 环境变量更改为 DevelopmentTest 以外的变量,或许可以解决您的问题。或者,如果您仍然想要自己的中间件,您可能应该删除 app.UseDeveloperExceptionPage(),甚至可能将自己的 app.UseRequestLoggingMiddleware() 移到 Configure 的第一行(尽管我不认为 Swagger 的东西应该干涉 - 但我不做任何承诺 :) )

我发现了问题。我需要的代码是

context.Response.StatusCode = 500;
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync($"Error on server processing request");

我注意到,如果我通过在 Web 浏览器中键入 url 来请求 API,我会取回文本,但是当我通过 Swagger UI 请求时,它是没有发送文本。

SwaggerUI 正在为请求设置 accept: text/plain header 因此 ASP.Net 忽略了任何未设置为这种类型的内容(ContentType 是 null 默认)。

浏览器在其接受 header 中有 */*,因此无论类型如何,都将发送内容。