ASP.NET Core 3.1中间件ILogger注入失效问题求助
我最近在学习ASP.NET Core 3.1的基础内容,尝试构建一个记录每个请求信息的中间件时,遇到了非常奇怪的日志行为,折腾了好一会儿才找到原因,分享给大家:
遇到的异常日志行为
情况1:指定名称创建Logger正常工作
通过ILoggerFactory创建指定名称的Logger时,日志可以正常输出:public ContextRequestLoggingMiddleware( RequestDelegate next, ILoggerFactory loggerFactory ) { this._next = next; _logger = loggerFactory.CreateLogger( "ContextRequestLoggingMiddleware" ); }对应的
InvokeAsync方法里执行_logger.LogInformation( "test from middleware" )能正常记录日志。情况2:泛型Logger/注入ILogger
无输出,注入ILogger报错
当使用泛型方式创建Logger(_logger = loggerFactory.CreateLogger<ContextRequestLoggingMiddleware>();)或者直接注入ILogger<ContextRequestLoggingMiddleware>时,代码执行到日志语句却没有任何日志输出,也没有报错;如果尝试注入普通的ILogger,会直接抛出运行时错误:Unable to resolve service for type 'Microsoft.Extensions.Logging.ILogger' while attempting to activate 'Microsoft.AspNetCore.Builder.ContextRequestLoggingMiddleware'情况3:调试无明显差异,控制器中ILogger
正常
调试时查看WatchList,没发现Logger对象有什么差异,而且控制器里的ILogger<T>是可以正常使用的。
我的项目相关代码
CreateHostBuilder代码
public static IHostBuilder CreateHostBuilder( string[] args ) => Host.CreateDefaultBuilder( args ) .ConfigureLogging( ( hostContext, loggingBuilder ) => { loggingBuilder.ClearProviders(); loggingBuilder.AddConfiguration( hostContext.Configuration.GetSection( "Logging" ) ); loggingBuilder.AddCustomFileLogger(); }) .ConfigureWebHostDefaults( webBuilder => { webBuilder.UseStartup<Startup>(); } );
Startup类相关代码
public void ConfigureServices( IServiceCollection services ) { services.AddControllers(); services.AddDbContext<NPAContext>( options => options.UseSqlServer( Configuration.GetConnectionString( cnnDB ) ) ); services.AddAuthentication( options => { options.DefaultAuthenticateScheme = ApiKeyAuthenticationOptions.DefaultScheme; options.DefaultChallengeScheme = ApiKeyAuthenticationOptions.DefaultScheme; }) .AddApiKeySupport( options => { } ); services.AddSingleton<List<JobEventDTO>>(); } public void Configure( IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory ) { if ( env.IsDevelopment() ) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseContextRequestLoggingMiddleware(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints( endpoints => { endpoints.MapControllers(); } ); }
问题解决方法
最终发现问题出在中间件的命名空间上!我之前把中间件放在了Microsoft.AspNetCore.Builder命名空间下,把它改成自定义的命名空间(比如NPARetrieval.Middleware)之后,泛型CreateLogger<T>和注入ILogger<T>的方式都正常工作了。修改后的代码如下:
namespace NPARetrieval.Middleware { public class ContextRequestLoggingMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; public ContextRequestLoggingMiddleware( RequestDelegate next, ILogger<ContextRequestLoggingMiddleware> logger ) { this._next = next; _logger = logger; } public async Task InvokeAsync (HttpContext context ) { _logger.LogInformation( "test from middleware" ); await _next( context ); } } }
内容的提问来源于stack exchange,提问作者Matus

