When setting up the database in the ConfigureServices() function there's a warning that says:
Calling 'BuildServiceProvider' from application code results in an additional copy of singleton services being created. Consider alternatives such as dependency injecting services as parameters to 'Configure'.
Here's following the piece of code that's references to that warning:
services.AddEntityFrameworkNpgsql()
.AddDbContext<AppDbContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString(EnvironmentContants.ConnectionString)))
.BuildServiceProvider();
EF Core version: 3.0
Database provider: PostgreSQL
Target framework: .NET Core 3.0
Operating system: Windows 10 x64
IDE: Visual Studio 2019 16.3.1
Is there any way to fix it?
Moved here since analyzer lives in this repo.
Why are you building the service provider.
@davidfowl I do as the NpgSQL documentation says about their SQL NuGet package at this link.
cc: @roji
Oops, seems like some old instructions... Have corrected the documentation. Thanks @smitpatel.
Yei, solved :D
Why are you building the service provider.
Any pointers as to how one should go about implementing Microsoft.AspNetCore.Hosting.IStartup without building the service provider in ConfigureServices?
It’s required there but IStartup is no longer supported with the generic host for this reason.
I am using the IOptions pattern for strongly typed AppSettings. In the past, I needed to specifically make a call to GetService so the IOptions
public void ConfigureServices(IServiceCollection services)
{
// Add App settings to a strongly typed configuration object
services.Configure<AppSettings>(Configuration);
// Create an instance of <AppSettings> so we can use it early in the startup process.
// By default, this service is not instantiated and available until later during the startup process.
var serviceProvider = services.BuildServiceProvider();
AppSettings = serviceProvider.GetService<IOptions<AppSettings>>();
// Add application specific services
services.AddApplicationAuthentication(AppSettings);
services.AddSoapService(AppSettings);
services.AddApplicationServices();
services.AddAppSwagger(AppSettings);
services.AddControllers().AddXmlSerializerFormatters();
}
Why don't you have those services resolve IOptions<AppSettings> instead of taking them directly in the Add* methods?
The problem is that when registering the IOptions<AppSettings> using services.Configure<AppSettings>(Configuration); is that that service is not immediately available for dependency injection during startup.
Can you show me an example of why you can’t defer resolution of IOptions\
I need an instance of HttpClient to request credentials from a key-value store inside my ConfigureServices method. How can I do that without building a ServiceProvider?
I'm also getting this message when attempting to use AddSwaggerGen:
services.AddSwaggerGen((options) =>
{
var provider = services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
...
}
All the documentation/examples I've seen for this online uses this code. Is there now a better way to do it?
@davidfowl, if I try to use dependency injection, the IOptions<AppSettings> is null. I could try to resolve it the static methods, but I would need to resolve it 3 different times, once for each static call.
I decided to just bind it manually in the startup.
public Startup(IConfiguration configuration)
{
Configuration = configuration;
Configuration.Bind(AppSettings);
}
private AppSettings AppSettings { get; } = new AppSettings();
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// Add App settings to a strongly typed configuration object for dependency injection
services.Configure<AppSettings>(Configuration);
// Add application specific services
services.AddApplicationAuthentication(AppSettings);
services.AddApplicationServices();
services.AddAppSwagger(AppSettings);
// Add controllers and additional serializer formatters
services.AddControllers().AddXmlSerializerFormatters();
}
Yes, of course I can instantiate it directly. But as you know the client itself have utilization issues, and I don't want to keep them in a library-level
From: David Fowler notifications@github.com
Sent: Thursday, October 10, 2019 2:13 AM
To: aspnet/AspNetCore AspNetCore@noreply.github.com
Cc: Kirill Taran kirill.taran@hotmail.com; Comment comment@noreply.github.com
Subject: Re: [aspnet/AspNetCore] Issue with BuildServiceProvider() in ConfigureServices() (#14587)
Create an HttpClient like so: new HttpClient()
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHubhttps://eur02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Faspnet%2FAspNetCore%2Fissues%2F14587%3Femail_source%3Dnotifications%26email_token%3DAEW5ABXGTL7S4GV5E3RSN7LQNZQQXA5CNFSM4I4ALDK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEAZXXTI%23issuecomment-540244941&data=02%7C01%7C%7Cdb05d89b06424107ec5408d74d0e4460%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637062595976518261&sdata=emsxKlZcGCwzq6A%2BqcT8RB7lSFwgovRTnH%2FbmqEfjo0%3D&reserved=0, or unsubscribehttps://eur02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAEW5ABTOPC3BBHSLKPQS5ITQNZQQXANCNFSM4I4ALDKQ&data=02%7C01%7C%7Cdb05d89b06424107ec5408d74d0e4460%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637062595976528266&sdata=FuEKdguOrSdTepkBO3oKHoEaHNAFZeIzRGT7w2shXso%3D&reserved=0.
Yes, of course I can instantiate it directly. But as you know the client itself have utilization issues, and I don't want to keep them in a library-level
It happens once at startup.
@Frankenleg
@davidfowl, if I try to use dependency injection, the IOptions
is null. I could try to resolve it the static methods, but I would need to resolve it 3 different times, once for each static call.
It can't be null. Can you show me exactly what code you wrote and what exactly is null?
Take one of those methods and make a minimal example of the pattern you're using.

i'm also geting this messsage when i try get db context to migrate it
@davidfowl please find a simple example with the logging builder when registering logging services.
services.AddLogging(loggingBuilder =>
{
using (var scope = loggingBuilder.Services.BuildServiceProvider().CreateScope())
{
var apiSettings = scope.ServiceProvider
.GetRequiredService<IOptions<ApiSettings>>()
.Value;
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.Enrich.WithProperty("ApiName", apiSettings.Name)
.Enrich.WithProperty("ApiVersion", apiSettings.Version)
.CreateLogger();
loggingBuilder.AddSerilog(Log.Logger, dispose: true);
}
});
I don't want to create an IOptions instance in the startup method's code just to do this. Is this the only way? Up until netcoreapp2.2 this was never an issue.
You can suppress the warning in that case. It’s an anti pattern in general. You can do it if you understand what exactly is happening and if you’re ok with it but there’s no support for building the container while trying to build it. What I mean is you have 2 containers and one of them will never be disposed.
PS: it was always an issue, we just warn you about it in 3.0
I still don't see a proper solution mentioned here, I am sure others like me are coming from Google and landing here.
There are lots of service collection extensions that take an options object or action. Many times, we do not have control over those (like the case with registering HttpClients, and this users comment here). So we do not have the luxury of injecting IOptions.
@davidfowl
What is the alternative to building the service provider all over again to get strongly typed and validated options to configure services that we register during startup?
Today, I do the following:
var isOptions = Configuration
.GetSection("IdentityServer")
.Get<IdentityServerOptions>();
This means I don't have to build the SP, and I get a strongly typed config for use in ConfigureServices. But it has other shortcomings compared to getting the IOptions<T> stuff registered already.
Most helpful comment
I'm also getting this message when attempting to use AddSwaggerGen:
All the documentation/examples I've seen for this online uses this code. Is there now a better way to do it?