Calling 'BuildServiceProvider' From Application Code Results In Copy Of Singleton Warning. How Do I Avoid This?


Answer :

If called BuildServiceProvider() in ConfigureServices, shown warning "Calling 'BuildServiceProvider' from application code results in a additional copy of Singleton services being created"

I solved this issue:

Create another function (which passed argument is IServiceCollection) and into the function call BuildServiceProvider()

enter image description here

For example your code it should be:

public void ConfigureServices(IServiceCollection services) {     if (HostingEnvironment.EnvironmentName == "Local")     {         services.AddHealthChecksUI()         .AddHealthChecks()         .AddCheck<TestWebApiControllerHealthCheck>("HomePageHealthCheck")         .AddCheck<DatabaseHealthCheck>("DatabaseHealthCheck");     }      services.Configure<PwdrsSettings>(Configuration.GetSection("MySettings"));     services.AddDbContext<PwdrsContext>(o => o.UseSqlServer(Configuration.GetConnectionString("PwdrsConnectionRoot")));      services.AddMvc(o =>     {         o.Filters.Add<CustomExceptionFilter>();     });      services.AddCors(options =>     {         options.AddPolicy("CorsPolicy", b => b             .SetIsOriginAllowed((host) => true)             .AllowAnyMethod()             .AllowAnyHeader()             .AllowCredentials());     });      services.AddSwaggerDocument();     services.AddHttpContextAccessor();      services.AddAutoMapper(typeof(ObjectMapperProfile));     services.AddTransient<IEmailSender, EmailSender>();     services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));     services.AddScoped(typeof(IAsyncRepository<>), typeof(Repository<>));     services.AddScoped<IRfReportTypeRepository, RfReportTypeRepository>();     services.AddScoped<IRfReportRepository, RfReportRepository>();     services.AddScoped<IRfReportLookupsService, RfReportLookupsService>();     services.AddScoped<IRfReportService, RfReportService>();      RegisterSerilogLogger logger = CreateRegisterSerilogLogger(services); }  private RegisterSerilogLogger CreateRegisterSerilogLogger(IServiceCollection services){         services.Configure<RAFLogging>(Configuration.GetSection("RAFLogging"));         ServiceProvider serviceProvider = services.BuildServiceProvider(); //No warning here ))         IOptions<RAFLogging> RAFLogger = serviceProvider.GetRequiredService<IOptions<RAFLogging>>();         RegisterSerilogLogger logger = new RegisterSerilogLogger(RAFLogger);     return logger; } 

Or use ApplicationServices of IApplicationBuilder. ApplicationSerivces's type is IServiceProvider.

I mention this solution is only for remove warning.

Calling BuildServiceProvider creates a second container, which can create torn singletons and cause references to object graphs across multiple containers.


UPDATED 24.01.2021

I read Adam Freeman's Pro ASP.NET Core 3 8th book. Adam Freeman used app.ApplicationServices instead of services.BuildServiceProvider() in page 157 for this purpose, that app is Configure method's parameter that this method located in Startup.cs

I thinks correct version is to use ApplicationServices property of app, which app is IApplicationBuilder in Configure method's parameter. ApplicationServices's type is IServiceProvider.

enter image description here

Adam Freeman's Pro ASP.NET Core 3 8th book : Pro ASP.NET Core 3

Adam Freeman's example project: SportStore project's Startup.cs, SportStore project's SeedData.cs

Microsoft's recommendations about DI : Dependency injection in ASP.NET Core

Similar questions' answers in Stackoverflow: https://stackoverflow.com/a/56058498/8810311, https://stackoverflow.com/a/56278027/8810311


Comments

Popular posts from this blog

Converting A String To Int In Groovy

"Cannot Create Cache Directory /home//.composer/cache/repo/https---packagist.org/, Or Directory Is Not Writable. Proceeding Without Cache"

Android How Can I Convert A String To A Editable