Sanket
Sanket

Reputation: 20017

Solving error - Unable to resolve service for type 'Serilog.ILogger'

I am trying to implement SeriLog in ASP.NET core application (.NET framework)

Below are steps I performed so far-

1) Added below references in Project.json

"Serilog": "2.2.0",
"Serilog.Extensions.Logging": "1.2.0",
"Serilog.Sinks.RollingFile": "2.0.0",
"Serilog.Sinks.File": "3.0.0"

2) Added following lines to the constructor of your Startup class-

Log.Logger = new LoggerConfiguration()
           .MinimumLevel.Debug()
           .WriteTo.RollingFile(Path.Combine(env.ContentRootPath, "log-{Date}.txt"))
           .CreateLogger();

3) Added following line to the configure method of your Startup class-

loggerFactory.AddSerilog();

4) Injecting the logger to HomeController like this-

ILogger logger;

    public HomeController(ILogger logger)
    {
        this.logger = logger;
    }

5) In About action, trying to log exception like this-

public IActionResult About()
    {
        ViewData["Message"] = "Your application description page.";

        try
        {
            throw new Exception("Serilog Testing");
        }
        catch (System.Exception ex)
        {
            this.logger.Error(ex.Message);
        }

        return View();
    }

On running my application, I am getting below error-

System.InvalidOperationException: Unable to resolve service for type 'Serilog.ILogger' while attempting to activate 'AspNetCore_SeriLog_trial1.Controllers.HomeController'. at Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
at lambda_method(Closure , IServiceProvider , Object[] ) at Microsoft.AspNetCore.Mvc.Internal.TypeActivatorCache.CreateInstance[TInstance](IServiceProvider serviceProvider, Type implementationType) at Microsoft.AspNetCore.Mvc.Controllers.DefaultControllerActivator.Create(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Controllers.DefaultControllerFactory.CreateController(ControllerContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__26.MoveNext()

Could anyone please help me on this? Any configuration missing for Serilog?

Upvotes: 39

Views: 51771

Answers (7)

fomoshlo
fomoshlo

Reputation: 1

My(!) Simplest solution for NET7.0 using the recommended Host.CreateApplicationBuilder(args); MS Learn: Worker services in .Net

NuGetPackages:

  • Serilog
  • Serilog.Extensions.Hosting
  • Serilog.Sinks.Console
  • Serilog.Sinks.File

    public static void Main(string[] args)
            {
                Log.Logger = new LoggerConfiguration()
                   .MinimumLevel.Debug()
                   .WriteTo.Console(LogEventLevel.Information)
                   .WriteTo.File(path:"logs/Dummylog-.txt",rollingInterval:RollingInterval.Day)
                   .CreateLogger();
    
    
                var builder = Host.CreateApplicationBuilder(args);
                var services = builder.Services;
                builder.Logging.ClearProviders();
    
                services.AddSerilog(Log.Logger)
                        .AddHostedService<Worker>();
                      
                IHost host = builder.Build();
                host.Run();
            }

in the Service i injected the Serilog(!).ILogger MS also has a ILogger interface, i could just write a using , but was lazy


    private readonly Serilog.ILogger _logger;
    
            public Worker(Serilog.ILogger logger)
            {
                _logger = logger;
            }
    
            protected override async Task ExecuteAsync(CancellationToken stoppingToken)
            {
                while (!stoppingToken.IsCancellationRequested)
                {
                    _logger.Information("Worker running at: {time}", DateTimeOffset.Now);
                    await Task.Delay(1000, stoppingToken);
                }
            }
        }

Upvotes: 0

computercarguy
computercarguy

Reputation: 2453

I know this is an old Question, but I just ran into this problem and found a different solution.

I switched out Microsoft.Extensions.Logging for Serilog, but I missed removing it from the constructor parameter list.

public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment, ILogger logger)

Once I removed that parameter, the error disappeared.

public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment)

It looks like the OP was trying to inject the logger through the constructor, but instead should have created a specific logger for that controller. You can also make it static so there's only 1 creation of the logger for every time this project runs, instead of 1 for every instance of the class.

public class HomeController : Controller
{
    private static readonly ILogger Logger = Log.ForContext<HomeController>();
    ...

    public HomeController(IIdentityServerInteractionService interaction, IWebHostEnvironment environment)
    {
    ...
    }

    ...
}

Apparently, what's happening is that the compiler tries to give the constructor a Microsoft.Extensions.Logging logger by default, instead of trying to match the Serilog logger the constructor is actually expecting, so that's where the error comes from.

Upvotes: -1

Marcello
Marcello

Reputation: 1289

If you need to use ILogger (from Serilog) instead of ILogger<HomeController> (from Microsoft.Extensions.Logging), you can register ILogger on your Startup class:

services.AddSingleton(Log.Logger);

Upvotes: 49

I was getting this issue "unable to resolve service for type 'interface_name' while attempting to activate 'Controller_Name' ....

By adding the below line in startup.cs I have resolved the same:

services.AddScoped<interface_name, Controller_Name>();

Upvotes: -1

Jon Story
Jon Story

Reputation: 3031

Which of the following two lines do you have in your controller?

using Serilog;
using Microsoft.Extensions.Logging;

If it's the former (using Serilog;) then that's probably your problem.

When you register the service, you're essentially saying "When a constructor asks for an Microsoft.Extensions.Logging.ILogger, pass them a Serilog instance because I'm using Serilog for my logging", but then in your constructor you aren't asking for Microsoft.Extensions.Logging.ILogger, you're asking for Serilog.ILogger and your application is getting confused, because you haven't defined an service to be injected for Serilog.ILoger, you've defined one for Microsoft.Extensions.Logging.ILogger

Remember that you are implementing Microsoft's ILogger interface: your constructor doesn't need to know that you're using Serilog... in fact, you don't want it to! The entire point is that you can swap Serilog out for a different logger at any time without having to change your code.

Change using Serilog; to using Microsoft.Extensions.Logging; in your constructor, and you'll be requesting the correct service type

Upvotes: 15

Mselmi Ali
Mselmi Ali

Reputation: 1257

You missed to inject your interface in the controller constructor:

ILogger<HomeController> logger = null;

public HomeController(ILogger<HomeController> _logger)
{
    logger = _logger;
}

In the Program.cs you have to add UseSerilog also:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseSerilog();

Upvotes: 0

dotnetstep
dotnetstep

Reputation: 17485

Try to do following thing in your controller.

    ILogger<HomeController> logger = null;
    public HomeController(ILogger<HomeController> _logger)
    {
        logger = _logger;
    }

Upvotes: 42

Related Questions