#c# #asp.net-core #dependency-injection #middleware #ilogger
#c# #asp.net-core #внедрение зависимостей #промежуточное программное обеспечение #ilogger
Вопрос:
Пытаюсь создать промежуточное программное обеспечение, которое регистрировало бы информацию для каждого запроса. ASP.NET Ядро 3.1 Изучение некоторых основ
Я пытаюсь понять какое-то странное поведение. Это мой конструктор для промежуточного программного обеспечения:
public ContextRequestLoggingMiddleware( RequestDelegate next, ILoggerFactory loggerFactory ) {
this._next = next;
_logger = loggerFactory.CreateLogger( "ContextRequestLoggingMiddleware" );
}
Использование этого работает так, как ожидалось. Сообщение регистрируется при каждом запросе:
public async Task InvokeAsync (HttpContext context ) {
_logger.LogInformation( "test from middleware" );
await _next( context );
}
Когда я использую код ниже:
_logger = loggerFactory.CreateLogger<ContextRequestLoggingMiddleware>();
Выполнение продолжается _logger.LogInformation
, но кажется, что оно не выполняется, ничего не регистрируется, никаких ошибок, никаких проблем, просто переходит к следующей строке кода. Просматривая _logger с помощью списка наблюдения, я не вижу никакой разницы между этими двумя подходами.
То же поведение, когда ничего не регистрируется, и ошибка не возникает, если я использую ILogger<T>
:
public ContextRequestLoggingMiddleware( RequestDelegate next,
ILogger<ContextRequestLoggingMiddleware> logger ) {
this._next = next;
_logger = logger;
}
Я не могу ввести обычный ILogger
, поскольку он выдает ошибку времени выполнения:
Не удалось разрешить службу для типа ‘Microsoft.Расширения.Ведение журнала.ILogger’ при попытке активировать ‘Microsoft.AspNetCore.Builder.ContextRequestLoggingMiddleware’.
Снова проверяя объект, я не вижу разницы между различными подходами, которые я использовал. Так почему же это?Я бы 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();
} );
}
Редактировать
Разрешение:
Я допустил ошибку, и при создании класса ContextRequestLoggingMiddleware
я поместил его в пространство Microsoft.AspNetCore.Builder
имен. При этом единственным способом заставить logger работать в промежуточном программном обеспечении была передача ILoggerFactory и создание logger, но это работало только одним способом
_logger = loggerFactory.CreateLogger( "ContextRequestLoggingMiddleware" )
Как только я поместил класс в другое пространство имен, начали работать и другие подходы
_logger = loggerFactory.CreateLogger<ContextRequestLoggingMiddleware>()
А также передача ILogger<ContextRequestLoggingMiddleware>
теперь работает
Итак, построение класса, как показано ниже, теперь работает для меня. Интересно, как изменение пространства имен заставляет его работать.
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 );
}
}
}
Комментарии:
1. Что происходит, если вы явно вводите
ILogger<ContextRequestLoggingMiddleware>
? Зачем использовать фабрику для начала?2. @Nkosi Как написано, он компилируется и запускается, но строка кода _logger . LogInformation не выполняется, он просто проходит через него. Единственный способ, которым мне удалось зарегистрировать что-то из промежуточного программного обеспечения, — это использовать factory. В этом причина вопроса, пытаясь понять, почему работает только один подход, но не другие.
3. Проблема почти наверняка заключается в вашем вызове
loggingBuilder.ClearProviders()
.