未传递自定义中间件异常处理程序响应内容
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
环境变量更改为 Development
或 Test
以外的变量,或许可以解决您的问题。或者,如果您仍然想要自己的中间件,您可能应该删除 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 中有 */*
,因此无论类型如何,都将发送内容。
我在使用 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
环境变量更改为 Development
或 Test
以外的变量,或许可以解决您的问题。或者,如果您仍然想要自己的中间件,您可能应该删除 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 中有 */*
,因此无论类型如何,都将发送内容。