In a .NET Core 3.1 project, one may configure Data Protection in ConfigureServices like below:
public void ConfigureServices(IServiceCollection services)
{
// ...
var sp = services.BuildServiceProvider();
services.AddDataProtection()
.AddKeyManagementOptions(o => o.XmlRepository = sp.GetService<IXmlRepository>());
}
This raises below warning (which makes sense):
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'.
I'm using a service provider there because my implementation of IXmlRepository has a dependency to a singleton service.
What would be the recommended way of providing my IXmlRepository implementation without having to build the service provider (and thus making additional copies of singleton services)?
⚠Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
I am having the same issue with this trying to call services.BuildServiceProvider().GetDataProtectionProvider(). What is the correct way to inject it ?
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDataProtection();
var dpp = services.BuildServiceProvider().GetDataProtectionProvider();
services.AddSingleton<IDataProtectionProvider>(dpp);
}
It looks like the EF Core persistence support created a wrapper that creates temporary scopes. See here . That nuget package actually eliminated our need for any of our custom stuff.
I had this problem too because MyDataStore is a singleton, inspired by EF implementation I managed to do this:
C#
services.AddDataProtection().Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(serv =>
{
return new ConfigureOptions<KeyManagementOptions>(options =>
{
options.XmlRepository = new MyXmlRepository(serv.GetService<IMyDataStore>());
});
});
@Tratcher or @davidfowl , can you suggest the recommendations here?
@stefanb05's answer is good.
We added more convenient helpers for this:
C#
services.AddOptions<KeyManagementOptions>()
.Configure<IMyDataStore>((options, store) =>
{
options.XmlRepository = new MyXmlRepository(store);
});
It removes the clunky calls to GetService and hides IConfigureOptions<T>
Doesn't that use an odd lifetime?
Most helpful comment
I had this problem too because MyDataStore is a singleton, inspired by EF implementation I managed to do this:
C# services.AddDataProtection().Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(serv => { return new ConfigureOptions<KeyManagementOptions>(options => { options.XmlRepository = new MyXmlRepository(serv.GetService<IMyDataStore>()); }); });