使用中间件的全局异常处理在 ASP.Net Core 应用程序中不起作用

Posted

技术标签:

【中文标题】使用中间件的全局异常处理在 ASP.Net Core 应用程序中不起作用【英文标题】:Global Exception Handling using Middleware not working in ASP.Net Core app 【发布时间】:2021-12-26 14:56:54 【问题描述】:

我一直在尝试在我的 ASP.Net Core Web API 中设置使用自定义中间件的全局异常处理。我需要使用 Serilog 将它们记录到日志文件中。我尝试了很多,但我无法让它工作。希望这里的朋友能帮帮我。

我的自定义中间件:

    public class ExceptionHandlingMiddleware

    private readonly RequestDelegate _next;
    private readonly ILogger<ExceptionHandlingMiddleware> logger;

    public ExceptionHandlingMiddleware()
    

    

    public ExceptionHandlingMiddleware(
        RequestDelegate next,
        ILogger<ExceptionHandlingMiddleware> logger)
    
        _next = next ?? throw new ArgumentNullException(nameof(next));
        this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
    

    public async Task InvokeAsync(HttpContext context)
    
        if (context is null)
        
            throw new ArgumentNullException(nameof(context));
        

        try
        
            await _next.Invoke(context);
        
        catch (Exception ex)
        
            await HandleExceptionAsync(context, ex);
        
    

    private async Task HandleExceptionAsync(
        HttpContext context,
        Exception exception)
    
        try
        
            int statusCode = 0;

            if (context is null)
            
                throw new ArgumentNullException(nameof(context));
            

            if (exception is null)
            
                throw new ArgumentNullException(nameof(exception));
            

            this.logger.LogError(exception.ToString());

            CustomApiResponse<CustomApiErrorResponse> errorResponse = null;

            if (exception is MyException myExceptionInfo)
            
                statusCode = myExceptionInfo.StatusCode == default ? (int)HttpStatusCode.InternalServerError : myExceptionInfo.StatusCode;
                errorResponse = new CustomApiResponse<CustomApiErrorResponse>()
                
                    StatusCode = statusCode,
                    TraceId = context.TraceIdentifier,
                    Response = new CustomApiErrorResponse()
                    
                        Message = myExceptionInfo.ErrorMessage,
                        StackTrace = myExceptionInfo.StackTrace
                    
                ;
            
            else
            
                statusCode = (int)HttpStatusCode.InternalServerError;
                const string message = "Unexpected error";
                errorResponse = new CustomApiResponse<CustomApiErrorResponse>()
                
                    StatusCode = (int)HttpStatusCode.InternalServerError,
                    Response = new CustomApiErrorResponse()
                    
                        Message = message,
                    ,
                    TraceId = context.TraceIdentifier
                ;
            

            var responseContent = JsonConvert.SerializeObject(errorResponse);

            context.Response.ContentType = "application/json";
            context.Response.StatusCode = statusCode;
            await context.Response.WriteAsync(responseContent);

        
        catch (Exception ex)
        
            this.logger.LogError(ex.ToString());
            throw;
        
    


Startup.cs

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
    
        //app.UseExceptionHandlerMiddleware();

        app.UseExceptionHandler(new ExceptionHandlerOptions
        
            ExceptionHandler = new ExceptionHandlingMiddleware().InvokeAsync,
        );

        //app.UseExceptionHandler(options =>
        //
        //    options.Run(async context =>
        //    
        //        // Exception Handling Code
        //    );
        //
    

我哪里错了?我还需要做什么才能让它工作吗?异常会从代码中抛出,但不会被中间件捕获。请朋友们帮帮我。

更新

我使用的是 GraphQL 而不是 REST。所以我的应用程序中没有控制器。这是造成这个问题的原因吗?

【问题讨论】:

嗨@Arjun D Nair,I'm using GraphQL instead of REST. So there are no controllers in my app. Is that a reason for this issue? 我想是的。我在 api 控制器中测试。效果很好。 嗨@Rena,感谢您的支持。我也提到了我使用 REST 完成的几个旧项目。在那些项目中它工作得很好,但在这个项目中却不行。 嗨@Rena,似乎使用 GraphQL 是个问题。我也使用 REST API 示例项目对其进行了测试,并且运行良好。现在我需要弄清楚为什么它在 GraphQL 中不起作用以及如何使它起作用。无论如何,谢谢你为我腾出一些时间。 【参考方案1】:

确保您的ExceptionHandlingMiddleware.cs 位于Middleware 文件夹中。

并在您的配置方法中使用以下内容:-

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        
            app.UseMiddleware<ExceptionHandlingMiddleware>();

           ...

它将解决您的问题。如果仍然无法解决,请告诉我。

【讨论】:

嗨,Pritom,我按照你说的试过了。我的中间件位于我的解决方案中的一个类库项目中。我将其移至 Startup.cs 文件所在的主 API 项目,并将文件夹重命名为 Middleware 并更改了命名空间。它似乎仍然不起作用。 @ArjunDNair 能给我看看你的项目文件夹目录图片吗? 对不起,这是一个受版权保护的项目。 @ArjunDNair 我实际上只是想查看您的启动文件、中间件文件夹及其异常类位置。 我猜是位置问题。我想确认一下。如果不是位置问题,我会更新你的异常处理类代码。【参考方案2】:

尝试像这样改变你的创业公司:

app.UseMiddleware<ExceptionHandlingMiddleware>();

而不是

app.UseExceptionHandler(new ExceptionHandlerOptions

    ExceptionHandler = new ExceptionHandlingMiddleware().InvokeAsync,
);

【讨论】:

我也试过了。它似乎仍然不起作用。

以上是关于使用中间件的全局异常处理在 ASP.Net Core 应用程序中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

ASP.Net Core 异常处理中间件

使用 NLog 在 ASP.NET Web API 2.1 中进行全局异常处理?

ASP.NET MVC中注册Global.asax的Application_Error事件处理全局异常

如何在 ASP.NET Core 中为 gRPC 服务添加全局异常处理 ?

处理asp.net核心中的异常?

ASP.NET全局错误处理和异常日志记录以及IIS配置自定义错误页面