Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

ASP.NET Core 8 Web API: cannot register scoped service from singleton

In my API I register some services with AddHostedService that need some interfaces to be injected on them, for example:

Program.cs:

builder.Services.AddScoped<IHypervisorRepository, HypervisorRepository>();
builder.Services.AddScoped<IAccountRepository, AccountRepository>();
builder.Services.AddScoped<ICloudStackDbUnitOfWork, CloudStackDbUnitOfWork>();
builder.Services.AddScoped<ICloudStackCoreConnectionFactory, MySqlCloudStackCoreConnectionFactory>();

builder.Services.AddScoped<IJobUtility, JobUtility>();
builder.Services.AddScoped<IVdcUnitOfWork, VdcUnitOfWork>();
builder.Services.AddScoped<IMemoryCache, MemoryCache>();

builder.Services.AddHostedService<CheckDatabaseHealthBackgroundService>();

CheckDatabaseHealthBackgroundService.cs:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

public sealed class CheckDatabaseHealthBackgroundService : BackgroundService, IDisposable
{
    private readonly IServiceProvider _provider;
    private readonly IJobUtility _jobUtility;
    private readonly IVdcUnitOfWork _unitOfWork;
    private readonly ICloudStackCoreConnectionFactory _connFactory;
    private readonly IMemoryCache _cache;
    private readonly ILogger<CheckDatabaseHealthBackgroundService> _logger;
    
    public CheckDatabaseHealthBackgroundService(
        IServiceProvider provider,
        IJobUtility jobUtility,
        IVdcUnitOfWork unitOfWork,
        ICloudStackCoreConnectionFactory connFactory,
        IMemoryCache cache,
        ILogger<CheckDatabaseHealthBackgroundService> logger)
    {
        _provider = provider;
        _jobUtility = jobUtility;
        _unitOfWork = unitOfWork;
        _connFactory = connFactory;
        _cache = cache;
        _logger = logger;
    }

but after I launch the API the following Exception is thrown:

System.InvalidOperationException: Error while validating the service descriptor ‘ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: CloudStackData.WebAPI.RefreshDiskTypeBackgroundService’: Cannot consume scoped service ‘Vdc.Libs.Data.IVdcUnitOfWork’ from singleton ‘Microsoft.Extensions.Hosting.IHostedService’.

System.InvalidOperationException: Cannot consume scoped service ‘Vdc.Libs.Data.IVdcUnitOfWork’ from singleton ‘Microsoft.Extensions.Hosting.IHostedService’

After reading about this error I concluded I should add the CheckDatabaseHealthBackgroundService required services as singleton, not scoped, and so I tried:

Program.cs:

builder.Services.AddScoped<IHypervisorRepository, HypervisorRepository>();
builder.Services.AddScoped<IAccountRepository, AccountRepository>();
builder.Services.AddScoped<ICloudStackDbUnitOfWork, CloudStackDbUnitOfWork>();
builder.Services.AddScoped<ICloudStackCoreConnectionFactory, MySqlCloudStackCoreConnectionFactory>();

builder.Services.AddSingleton<IJobUtility, JobUtility>();
builder.Services.AddSingleton<IVdcUnitOfWork, VdcUnitOfWork>();
builder.Services.AddSingleton<IMemoryCache, MemoryCache>();

builder.Services.AddHostedService<CheckDatabaseHealthBackgroundService>();

And now the Exception thrown is:

System.InvalidOperationException: Error while validating the service descriptor ‘ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: CloudStackData.WebAPI.RefreshDiskTypeBackgroundService’: Cannot consume scoped service ‘Vdc.Libs.Data.DbContextWrite’ from singleton ‘Vdc.Libs.Data.IVdcUnitOfWork’.

And here I started to be stuck.

VdcUnitOfWork is a custom class we created:

public sealed class VdcUnitOfWork : EFDbUnitOfWork<DbContextWrite>, IVdcUnitOfWork, IUnitOfWork, IDisposable, IDbContextWrapper
{
    public VdcUnitOfWork(DbContextWrite dbContext)
        : base(dbContext)
    {
    }
}

And DbContextWrite is another custom class:

public abstract class DbContextWrite : DbContext
{
    protected DbContextWrite([NotNull] DbContextOptions options)
        : base(options)
    {
    }
}

The fact is after adding the hosted service with AddHostedService I cannot run the API anymore (I have four hosted services, but just put one for the sake of simplification).

Any help?

>Solution :

For using scoped-Services in a HostedService, which is a singleton, you need to inject the IServiceScopeFactory (using primary constructors from .NET 8.0):

public sealed class CheckDatabaseHealthBackgroundService
      (IServiceScopeFactory scopeFactory) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
         // get scoped services:
         using var scope = scopeFactory.CreateScope();
         var jobUtility = scope.ServiceProvider.GetService<IJobUtility>();
         var unitOfWork = scope.ServiceProvider.GetService<IVdcUnitOfWork>();
         var memoryCache = scope.ServiceProvider.GetService<IMemoryCache>();

         // Use services here
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading