user13409315
user13409315

Reputation: 169

Unable to resolve service for type 'Microsoft.AspNetCore.DataProtection.IDataProtector'

I have a custom service which in that I'm using Microsoft's IDataProtector. I have registered my service in startup with AddScoped but i have a problem with using IDataProtector.

error message:

Unable to resolve service for type 'Microsoft.AspNetCore.DataProtection.IDataProtector' while attempting to activate 'Service'.

here is my code :

public class Service: IInjectable
{
    private readonly IDataProtector _protector;
     
    public Service(IDataProtector protector)
    {
      _protector = protector.CreateProtector("key");
    }

    other code ...
}

The way I have registered my service:

    public static void RegisterScoped<T>(
        this IServiceCollection services, params Assembly[] assemblies)
    {
        IEnumerable<Type> types = assemblies.SelectMany(a => a.GetExportedTypes())
            .Where(c => c.IsClass && typeof(T).IsAssignableFrom(c));

        foreach (var item in types)
            services.AddScoped(item);
    }

StartUp :

 services.RegisterScoped<IInjectable>(typeof(IInjectable).Assembly);

Upvotes: 4

Views: 7238

Answers (2)

Vitaliy Markitanov
Vitaliy Markitanov

Reputation: 2448

I run into the same situation one day as well and had to go through source code of class method AddDataProtection() of class DataProtectionServiceCollectionExtensions in assembly Microsoft.AspNetCore.DataProtection.dll.

For those who is interested in details how registration of DataProtection service happens this is extract of code where actual magic happens:

private static void AddDataProtectionServices(IServiceCollection services)
{
    if (OSVersionUtil.IsWindows())
    {
        // Assertion for platform compat analyzer
        Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));
        services.TryAddSingleton<IRegistryPolicyResolver, RegistryPolicyResolver>();
    }

    services.TryAddEnumerable(
        ServiceDescriptor.Singleton<IConfigureOptions<KeyManagementOptions>, KeyManagementOptionsSetup>());
    services.TryAddEnumerable(
        ServiceDescriptor.Singleton<IPostConfigureOptions<KeyManagementOptions>, KeyManagementOptionsPostSetup>());
    services.TryAddEnumerable(
        ServiceDescriptor.Transient<IConfigureOptions<DataProtectionOptions>, DataProtectionOptionsSetup>());

    services.TryAddSingleton<IKeyManager, XmlKeyManager>();
    services.TryAddSingleton<IApplicationDiscriminator, HostingApplicationDiscriminator>();
    services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, DataProtectionHostedService>());

    // Internal services
    services.TryAddSingleton<IDefaultKeyResolver, DefaultKeyResolver>();
    services.TryAddSingleton<IKeyRingProvider, KeyRingProvider>();

    services.TryAddSingleton<IDataProtectionProvider>(s =>
    {
        var dpOptions = s.GetRequiredService<IOptions<DataProtectionOptions>>();
        var keyRingProvider = s.GetRequiredService<IKeyRingProvider>();
        var loggerFactory = s.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;

        IDataProtectionProvider dataProtectionProvider = new KeyRingBasedDataProtectionProvider(keyRingProvider, loggerFactory);

        // Link the provider to the supplied discriminator
        if (!string.IsNullOrEmpty(dpOptions.Value.ApplicationDiscriminator))
        {
            dataProtectionProvider = dataProtectionProvider.CreateProtector(dpOptions.Value.ApplicationDiscriminator);
        }

        return dataProtectionProvider;
    });

    services.TryAddSingleton<ICertificateResolver, CertificateResolver>();
}

As you can see here, only IDataProtectionProvider registered in line services.TryAddSingleton<IDataProtectionProvider> and nothing mentions IDataProtector.

Upvotes: 2

user13409315
user13409315

Reputation: 169

Finally , i found the problem :

i had to use IDataProtectionProvider instead of IDataProtector in my service constructor

Upvotes: 12

Related Questions