The primary goal is to reload user account data at regular 30-minute intervals within a .NET 5 API. In pursuit of this goal, I learned something about implementing background tasks to automate this process. Following a tutorial, I attempted to set up a background task, also having a scopedService. However, during the implementation, I encountered persistent errors:
1.
“No service for type ‘AccountRepository.AccountScopedService’ has been registered.”
Despite multiple troubleshooting attempts, including service registration checks, dependency injection verification, and rewatching the video, the error remains unresolved.
- If I undo the last step of the video and just use
IAccountSingletonService singletonService, IAccountTransientService transientServicein the ctor (that is, withoutIServiceProvider serviceProvider), the application freezes. Swagger is not loaded.
I appreciate your help.
AccountLoaderBackgroundService.cs
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace AccountRepository
{
public class AccountLoaderBackgroundService : BackgroundService
{
public readonly List<Person> AllPersons = new List<Person>();
private readonly IServiceProvider _serviceProvider;
private readonly IAccountSingletonService singletonService;
private readonly IAcountTransientService transientService;
public AccountLoaderBackgroundService(IAccountSingletonService singletonService,
IAcountTransientService transientService,
IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using (var scope = _serviceProvider.CreateScope())
{
var scopedService = scope.ServiceProvider.GetRequiredService<AccountScopedService>();
LoadAccounts();
System.Diagnostics.Debug.WriteLine("ExecuteAsync in AccountLoaderBackgroundService");
await Task.Delay(new TimeSpan(0, 30, 0));
}
}
}
public bool LoadAccounts()
{
// reading data
return true;
}
}
}
AccountLoaderHostedService.cs
using Microsoft.Extensions.Hosting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AccountRepository
{
public class AccountLoaderHostedService : IHostedService
{
public async Task StartAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
System.Diagnostics.Debug.WriteLine("StartAsync in AccountLoaderHostedService");
await Task.Delay(new TimeSpan(0, 30, 0));
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}
Startup.cs
services.AddSingleton<AccountRepository.IAccountSingletonService, AccountRepository.AccountSingletonService>();
services.AddScoped<AccountRepository.IAccountScopedService, AccountRepository.AccountScopedService>();
services.AddTransient<AccountRepository.IAcountTransientService, AccountRepository.AcountTransientService>();
services.AddHostedService<AccountRepository.AccountLoaderBackgroundService>();
services.AddHostedService<AccountRepository.AccountLoaderHostedService>();
Plus, I wrote the classes and interfaces for the 3 services.
public class AccountScopedService : IAccountScopedService
{
}
public class AccountSingletonService : IAccountSingletonService
{
}
public class AcountTransientService : IAcountTransientService
{
}
public interface IAccountScopedService
{
}
public interface IAccountSingletonService
{
}
public interface IAcountTransientService
{
}
It seems you're registering the interface
IAccountScopedServiceinstartup.cson line 2, but you're requesting the concrete classAccountScopedServiceinAccountLoaderBackgroundService.cson line 30. To fix this, you should requestIAccountScopedServiceinstead ofAccountScopedServiceon line 30 inAccountLoaderBackgroundService.cs.Hope it helps. If you have any questions, don't hesitate to contact me.
Kind regards Nico