You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在静态类实现的自定义错误处理中间件中添加日志?

解决方案

你可以通过两种方式在这个静态扩展类的错误处理中间件中添加日志功能,避免静态字段赋值的问题:

方法一:从HttpContext获取日志实例

在中间件的Run委托内部,通过HttpContext.RequestServices从依赖注入容器中获取ILogger实例,这是最直接的方式:

public static class ErrorHandlerExtensions
{
    public static void UseErrorHandler(this IApplicationBuilder app)
    {
        app.UseExceptionHandler(appError =>
        {
            appError.Run(async context =>
            {
                var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
                if (contextFeature == null) return;

                // 从请求服务中获取日志实例
                var logger = context.RequestServices.GetRequiredService<ILogger<ErrorHandlerExtensions>>();
                // 记录错误日志,包含异常详情和请求路径
                logger.LogError(contextFeature.Error, "未处理的异常发生,请求路径:{Path}", 
                    context.Request.Path);

                context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                context.Response.ContentType = "application/json";

                context.Response.StatusCode = contextFeature.Error switch
                {
                    BadRequestException => (int)HttpStatusCode.BadRequest,
                    OperationCanceledException => (int)HttpStatusCode.ServiceUnavailable,
                    NotFoundException => (int)HttpStatusCode.NotFound,
                    _ => (int)HttpStatusCode.InternalServerError
                };

                var errorResponse = new
                {
                    statusCode = context.Response.StatusCode,
                    message = contextFeature.Error.GetBaseException().Message
                };

                await context.Response.WriteAsync(JsonSerializer.Serialize(errorResponse));
            });
        });
    }
}

方法二:从IApplicationBuilder的服务容器获取日志实例

如果你想在中间件初始化时就拿到日志实例,可以通过app.ApplicationServices直接获取:

public static class ErrorHandlerExtensions
{
    public static void UseErrorHandler(this IApplicationBuilder app)
    {
        // 从应用服务容器中获取日志实例
        var logger = app.ApplicationServices.GetRequiredService<ILogger<ErrorHandlerExtensions>>();

        app.UseExceptionHandler(appError =>
        {
            appError.Run(async context =>
            {
                var contextFeature = context.Features.Get<IExceptionHandlerFeature>();
                if (contextFeature == null) return;

                logger.LogError(contextFeature.Error, "未处理的异常发生,状态码:{StatusCode}", 
                    context.Response.StatusCode);

                context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                context.Response.ContentType = "application/json";

                context.Response.StatusCode = contextFeature.Error switch
                {
                    BadRequestException => (int)HttpStatusCode.BadRequest,
                    OperationCanceledException => (int)HttpStatusCode.ServiceUnavailable,
                    NotFoundException => (int)HttpStatusCode.NotFound,
                    _ => (int)HttpStatusCode.InternalServerError
                };

                var errorResponse = new
                {
                    statusCode = context.Response.StatusCode,
                    message = contextFeature.Error.GetBaseException().Message
                };

                await context.Response.WriteAsync(JsonSerializer.Serialize(errorResponse));
            });
        });
    }
}

原写法错误原因

你尝试给readonly静态字段赋值是不允许的——readonly字段只能在静态构造函数或字段初始化时赋值。而且静态字段会被所有请求共享,这种方式在多线程场景下存在风险,也不符合ASP.NET Core依赖注入的设计原则。上面两种方法都是从依赖注入容器中获取日志实例,既符合框架设计规范,又能保证日志实例的正确生命周期。

内容的提问来源于stack exchange,提问作者angie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 03:35:13