How to resolve HostedService in Controller

Viewed 11467

I am trying to add a Background Timer in ASP.NET Core 3.0, which periodically executes a task. Google led me to this, where I implemented the 'Timed background tasks'. However, I'm stuck in resolving the HostedService in the controller. I need a specific instance of TimedHealthCheckService so I can call another public function called 'GetAvailableODataUrl()'.


In the startup.cs I use the following code:

services.AddHostedService<TimedHealthCheckService>();

The TimedHealthCheckService obviously implements IHostedService:

public class TimedHealthCheckService : IHostedService, IDisposable                  

In my controller, I have the following constructor:

public HealthCheckController(ILogger<HealthCheckController> logger, IHostedService hostedService)
{
  this.logger = logger;
  this.timedHealthCheckService = hostedService as TimedHealthCheckService;
}

However, when I start my WebAPI, the timedHealthCheckService is always null. It seems another IHostedService gets injected into the constructor. By checking hostedService, it is actually an object of type GenericWebHostService.

If I change the controller's constructor to:

public HealthCheckController(ILogger<HealthCheckController> logger, TimedHealthCheckService hostedService)

I am getting the following error:

Unable to resolve service for type 'HealthCheck.Web.TimedHealthCheckService' while attempting to activate 'HealthCheck.Web.Controllers.HealthCheckController'.

I also tried services.AddSingleton<IHostedService, TimedHealthCheckService>(); with the same result.

1 Answers

Try these two lines in startup.cs:

services.AddSingleton<TimedHealthCheckService>();
services.AddHostedService<TimedHealthCheckService>(provider => provider.GetService<TimedHealthCheckService>());

The first line above tells the service provider to create a singleton and give it to anyone who wants a TimedHealthCheckService, like your controller's constructor. However, the service provider is unaware that the singleton is actually an IHostedService and that you want it to call StartAsync().

The second line tells the service provider that you want to add a hosted service, so it'll call StartAsync() when the application starts running. AddHostedService accepts a Func<IServiceProvider,THostedService> callback. The callback we provide fetches the singleton TimedHealthCheckService from the service provider and returns it back to the service provider as an IHostedService. The service provider then calls its StartAsync() function.

And in your controller:

public HealthCheckController(ILogger<HealthCheckController> logger, TimedHealthCheckService hostedService)
Related