ASP.NET核心HttpContext.Response.StatusCode异常时为200
ASP.NET Core HttpContext.Response.StatusCode is 200 when exception
我有一个端点抛出异常。
[ApiController]
[Route("api")]
public class LegacyController : ControllerBase
{
[HttpPost("endpoint")]
public async Task<ActionResult<IEnumerable<Entitty>>> GetAll()
{
throw new Exception();
return Ok(t.ToList());
}
}
我有如下所示的自定义 Http 日志记录过滤器
using Microsoft.AspNetCore.Http;
namespace Client.API.Extensions
{
public class HttpLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public HttpLoggingMiddleware(RequestDelegate next, ILogger<HttpLoggingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
finally
{
_logger.LogInformation(
"Request {method} {url} => {statusCode}",
context.Request?.Method,
context.Request?.Path.Value,
context.Response?.StatusCode);
}
}
}
}
当我调用此端点时,context.Response?.StatusCode 为 200。为什么?
但是,Postman 告诉我我的请求失败了,我自己看到了错误,因此一切看起来都很正常。虽然日志包含 200 个状态代码消息,而不是 500 个。
编辑:这是我的启动(删除了一些部分)。
namespace Client.API
{
public class Startup
{
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseHttpsRedirection();
app.UsePathBase(new PathString(basePath));
app.UseRouting();
app.UseMiddleware<HttpLoggingMiddleware>();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
如果你想捕获异常,你需要使用特定的中间件--app.UseExceptionHandler();
,所以我首先使用这个中间件来设置日志。
密码是:
app.UseExceptionHandler(
appErr =>
{
appErr.Run(
async context =>
{
logger.LogInformation(
"Request {method} {url} => {statusCode}",
context.Request?.Method,
context.Request?.Path.Value,
context.Response?.StatusCode);
});
});
但是有一个问题,这个中间件只能捕获异常,所以当响应码不是500
时,请求不会进入这个中间件。
最后我换了一个方法,我用try/catch
来捕获异常,然后自己设置StatusCode
就成功了。代码如下:
public class HttpLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<HttpLoggingMiddleware> _logger;
public HttpLoggingMiddleware(RequestDelegate next,ILogger<HttpLoggingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception)
{
//catch the Exception and set the StatusCode
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
}
finally
{
_logger.LogInformation(
"Request {method} {url} => {statusCode}",
context.Request?.Method,
context.Request?.Path.Value,
context.Response?.StatusCode);
}
}
}
我有一个端点抛出异常。
[ApiController]
[Route("api")]
public class LegacyController : ControllerBase
{
[HttpPost("endpoint")]
public async Task<ActionResult<IEnumerable<Entitty>>> GetAll()
{
throw new Exception();
return Ok(t.ToList());
}
}
我有如下所示的自定义 Http 日志记录过滤器
using Microsoft.AspNetCore.Http;
namespace Client.API.Extensions
{
public class HttpLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public HttpLoggingMiddleware(RequestDelegate next, ILogger<HttpLoggingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
finally
{
_logger.LogInformation(
"Request {method} {url} => {statusCode}",
context.Request?.Method,
context.Request?.Path.Value,
context.Response?.StatusCode);
}
}
}
}
当我调用此端点时,context.Response?.StatusCode 为 200。为什么?
但是,Postman 告诉我我的请求失败了,我自己看到了错误,因此一切看起来都很正常。虽然日志包含 200 个状态代码消息,而不是 500 个。
编辑:这是我的启动(删除了一些部分)。
namespace Client.API
{
public class Startup
{
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseHttpsRedirection();
app.UsePathBase(new PathString(basePath));
app.UseRouting();
app.UseMiddleware<HttpLoggingMiddleware>();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
如果你想捕获异常,你需要使用特定的中间件--app.UseExceptionHandler();
,所以我首先使用这个中间件来设置日志。
密码是:
app.UseExceptionHandler(
appErr =>
{
appErr.Run(
async context =>
{
logger.LogInformation(
"Request {method} {url} => {statusCode}",
context.Request?.Method,
context.Request?.Path.Value,
context.Response?.StatusCode);
});
});
但是有一个问题,这个中间件只能捕获异常,所以当响应码不是500
时,请求不会进入这个中间件。
最后我换了一个方法,我用try/catch
来捕获异常,然后自己设置StatusCode
就成功了。代码如下:
public class HttpLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<HttpLoggingMiddleware> _logger;
public HttpLoggingMiddleware(RequestDelegate next,ILogger<HttpLoggingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception)
{
//catch the Exception and set the StatusCode
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
}
finally
{
_logger.LogInformation(
"Request {method} {url} => {statusCode}",
context.Request?.Method,
context.Request?.Path.Value,
context.Response?.StatusCode);
}
}
}