如何从 Rest API 中筛选出堆栈跟踪信息,只需返回"状态代码:500;内部服务器错误'?



我有一个。NET 5 wepapi。我已经创建了一个全局异常处理程序属性,并将其放在基本控制器类上。看起来像这个

public override void OnException(ExceptionContext context)
{
// All user exceptions implement IWebApiException
if (context.Exception is IWebApiException webApiException)
{
// Then return a problem detail
ObjectResult result = new ObjectResult(new ProblemDetails
{
Type = webApiException.Type,
Title = webApiException.Title ?? ReasonPhrases.GetReasonPhrase(webApiException.Status),
Status = webApiException.Status,
Detail = webApiException.Detail,
Instance = webApiException.Instance,
})
{
StatusCode = webApiException.Status
};
result.ContentTypes
.Add(new 
MediaTypeHeaderValue(newMicrosoft.Extensions.Primitives.StringSegment("application/problem+json")));

context.Result = result;
}

base.OnException(context);
}

其思想是,开发人员有意抛出的任何异常都将实现IWebApiException并返回标准的问题详细信息。然而,然后抛出一个不实现IWebApiException的异常,然后Rest API将整个堆栈跟踪返回给调用方,响应如下:

System.Exception: Test
at WebApplication1.Controllers.WeatherForecastController.Get() in C:DevProjectsodiam-dot-net-api-starterAPIControllersWeatherForecastController.cs:line 58
at lambda_method14(Closure , Object , Object[] )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ExceptionContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Builder.Extensions.UsePathBaseMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

相反,我希望返回一条简单的消息,如下所示:

Status Code: 500; Internal Server Error

在维护全局异常属性的同时,不必在try-catch中包装每个操作并返回new StatusCodeResult(StatusCodes.Status500InternalServerError)),实现这一点的最简单方法是什么?

解决方案比我预期的要简单。我最终创建了一个中间件:

public class ErrorHandlingMiddleware
{
private readonly RequestDelegate next;
public ErrorHandlingMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await next(context);
}
catch (Exception ex)
{
await HandleException(context, ex);
}
}
private static Task HandleException(HttpContext context, Exception ex)
{
// If the exception is not user based
if (ex is not IWebAPiException)
{
// 500 if unexpected
HttpStatusCode code = HttpStatusCode.InternalServerError; 

context.Response.ContentType = "text/plain";
context.Response.StatusCode = (int)code;

}
return context.Response.WriteAsync("Status Code: 500; Internal Server Error");
}
}

注册管道中的中间件:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseCors(APIConstants.Cors.AllowAll);
//app.UseDeveloperExceptionPage(); <= remove this line to ensure middleware is used
}

app.UseMiddleware<ErrorHandlingMiddleware>();
...
}

由于所有用户抛出的异常都应该实现IWebApiException,如果该异常没有实现它,那么只返回内部服务器错误500。

最新更新