I'm having problems using the logger in the context of a fire-and-forget background job with ASP.NET Core WebApi. When using logger.LogInformation("some message"). The following exception occurs:
Newtonsoft.Json.JsonSerializationException: Could not create an instance of type Microsoft.Extensions.Logging.ILogger. Type is an interface or abstract class and cannot be instantiated. Path '', line 1, position 2.
Obvisouly, it seems that hangfire is unable to resolve the instantion of the logger based on the parameters instructed in the application's bootstrap.
I am certain that:
- Hangfire is properly configured and works
- The logger (using Serilog) works when used in the same scope as the app (not in backgorund)
- Service injection works for background jobs for other services than the ILogger
Here is my configuration:
Program.cs
public static IWebHost BuildWebHost (string[] args) =>
WebHost.CreateDefaultBuilder (args)
.UseStartup<Startup> ()
.UseSerilog ()
.Build ();
Startup.cs
public Startup (IHostingEnvironment env) {
Log.Logger = new LoggerConfiguration ()
.MinimumLevel.Debug ()
.MinimumLevel.Override ("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext ()
.WriteTo.Console ()
.WriteTo.Debug ()
.WriteTo.RollingFile (System.IO.Path.Combine ("logs/{Date}-logs.txt"))
.CreateLogger ();
}
public void ConfigureServices (IServiceCollection services) {
services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(dispose: true));
// ... registering other services
services.AddMvc ();
services.AddHangfire (conf => conf.UseSqlServerStorage (Configuration.GetConnectionString ("HangFire")));
}
public void Configure (IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider) {
app.UseMvc ();
//hangfire
GlobalConfiguration.Configuration.UseActivator(new HangfireActivator(serviceProvider));
app.UseHangfireServer ();
app.UseHangfireDashboard ();
}
HangfireActivator
public class HangfireActivator : Hangfire.JobActivator {
private readonly IServiceProvider _serviceProvider;
public HangfireActivator (IServiceProvider serviceProvider) {
_serviceProvider = serviceProvider;
}
public override object ActivateJob (Type type) {
Debug.WriteLine("ActivateJob() => " + type.Name);
return _serviceProvider.GetService (type);
}
}
ValueController.cs
public class ValuesController : Controller {
private readonly ILogger<ValuesController> logger;
private readonly SomeService someService;
public ValuesController (ILogger<ValuesController> logger, SomeService someService) {
this.logger = logger;
this.someService = someService;
}
[Route ("task")]
public JsonResult StartTask () {
var server = new BackgroundJobServer ();
BackgroundJob.Enqueue(() => logger.LogInformation("HELLO from background job instanciated logger"));
return new JsonResult (new { Result = "task started" });
}
}
Am I missing something ? Any help or link to a related topic would be much appreciated. Thank you for your help !