【发布时间】:2021-06-08 00:23:17
【问题描述】:
我正在尝试在 .NetCore 3.1 webpai 中设置全局异常处理代码
我的目标是在应用退出之前使用 log4net 记录未处理的异常。
我尝试了几个教程,一个使用过滤器,几个使用中间件,当我完成并测试它时,当我抛出异常时,中间件永远不会被调用。
我已经有一个过滤器(它被注释掉以测试中间件以防它们交互),它确实有效,但不能使用 IOC 加载 ILogger 的实例
[HttpGet]
[Route( "/ThrowException" )]
public JqGridReturnCV ThrowException()
{
log.LogTrace( "AdStudentController::ThrowException() - in" );
throw new Exception( "This is a test Exception" );
log.LogTrace( "AdStudentController::ThrowException() - out" );
}
这是我的中间件代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using log4net;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using StudentPortal4Api.Dto;
namespace StudentPortal4Api.Utilities
{
public class GlobalExceptionMiddleware
{
private readonly RequestDelegate next;
public readonly ILogger log;
public GlobalExceptionMiddleware( RequestDelegate _next, ILogger _log )
{
next = _next;
log = _log;
}
public async Task Invoke( HttpContext context )
{
try
{
await next( context );
}
catch ( Exception ex )
{
var response = context.Response;
response.ContentType = "application/json";
switch ( ex )
{
default:
// unhandled error
log.Log( LogLevel.Error, " GlobalException:" + ex.ToString() );
break;
}
throw;
}
}
}
public class ErrorDetails
{
public int StatusCode { get; set; }
public string Message { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject( this );
}
}
public static class ExceptionMiddlewareExtensions
{
public static void ConfigureExceptionHandler( this IApplicationBuilder app, ILogger logger )
{
app.UseExceptionHandler( appError =>
{
appError.Run( async context =>
{
context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
context.Response.ContentType = "application/json";
var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
if ( contextFeature != null )
{
logger.LogError( $"Something went wrong: {contextFeature.Error}" );
await context.Response.WriteAsync( new ErrorDetails()
{
StatusCode = context.Response.StatusCode,
Message = "Internal Server Error."
}.ToString() );
}
} );
} );
}
}
}
这是我的配置方法,我怀疑我在注册时做错了
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure( IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, ILogger log )
{
//code removed for clarity
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
//Code removed for clarity
// global error handler
app.UseMiddleware<GlobalExceptionMiddleware>();
app.ConfigureExceptionHandler( log );
}
}
}
有人知道我做错了什么吗?
【问题讨论】:
-
请尝试将您共享的代码库减少到minimal reproducible example。现在它有太多不相关的代码(特别是 startup.cs)。
-
订单很重要。你不能只是把东西扔到
Configurewilly-nilly。您正在Configure中构建服务管道。尝试将app.UseExceptionHandler移到app.UseEndpoints行上方。 -
删除了更多不需要的代码。虽然我必须得到答案才能确定其中一些是不需要的,因为它是一个 OoOP 错误。
标签: c# asp.net-core asp.net-core-webapi