我正在寻找一种方法来返回调用我的 Web API 方法时发生的任何异常的详细信息。
默认情况下,在生产环境中,错误 500"内部服务器错误"是 API 返回的唯一信息。
它是一个私有 API,不会在互联网上发布,调用方应用程序需要获取并存储所有详细信息,以防异常。
异常详细信息可以是 HttpResponse 内容中格式化的 JSON,允许调用方读取 Message 属性和异常的 StackTraceString 属性(没有像 UseDeveloperExceptionPage 配置这样的 HTTP 页面(。
目前,默认的启动配置方法是:
public class Startup
{
[...]
public void Configure(IApplicationBuilder app, IHostingEnvironment env, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory)
{
loggerFactory.AddNLog();
env.ConfigureNLog(Path.Combine(AppContext.BaseDirectory, "nlog.config"));
if ( env.IsDevelopment() )
app.UseDeveloperExceptionPage();
else
app.UseStatusCodePages();
app.UseMvc();
}
}
你可以编写一个自定义中间件,它拦截所有异常并将它们返回给调用方:
public class ExceptionHandler
{
private readonly RequestDelegate _next;
public ExceptionHandler(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
var response = context.Response;
response.ContentType = "application/json";
response.StatusCode = (int)HttpStatusCode.InternalServerError;
await response.WriteAsync(JsonConvert.SerializeObject(new
{
// customize as you need
error = new
{
message = exception.Message,
exception = exception.GetType().Name
}
}));
}
}
并在启动配置方法中注册它:
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
else
app.UseMiddleware<ExceptionHandler>();
除了中间件,您可以创建 ActionFilterAttribute 并更改 IActionResult
下面是一个简单的示例属性,对于所有未处理的异常,使用异常方法返回 400 个错误请求。
public class MyUnhandledExceptionFilter : ActionFilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext context)
{
context.Result = new BadRequestObjectResult(context.Exception.Message);
}
}
然后,在启动的配置服务方法中注册它,如下所示
services.AddMvc(options =>
{
options.Filters.Add(typeof(MyUnhandledExceptionFilter));
})
这仅捕获到达 MVC 的异常,在大多数情况下,这是您需要的
记得在UseMvc(或.Net Core 3中的UseRouting (之前添加它,因为顺序很重要!!!!
app.UseRouting ();
app.UseMiddleware (typeof (ErrorHandlingMiddleware));