Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve HostedService in Controller

Tags:

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.

like image 225
Fabian Bigler Avatar asked Oct 15 '19 15:10

Fabian Bigler


People also ask

Can a controller have a constructor?

You need to pass controller namespace (using constructor) so every controller should be same namespace and. All controllers need single parameterized construction which accept ILogger object only. Without that it will throw MissingMethodException .

How can we inject the service dependency into the controller?

ASP.NET Core injects objects of dependency classes through constructor or method by using built-in IoC container. The built-in container is represented by IServiceProvider implementation that supports constructor injection by default.

Can we inject the dependency to individual action method of the controller?

You can take advantage of the ServiceFilter attribute to inject dependencies in your controller or your controller's action methods.


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) 
like image 89
Jeffrey Rennie Avatar answered Sep 18 '22 22:09

Jeffrey Rennie