简体   繁体   中英

ASP.NET Core Web API - Unable to resolve service for type 'Serilog.ILogger' while attempting to activate 'AuthService'

In ASP.NET Core-6 Web API, I have this code:

BaseController:

[Produces("application/json")]
[ApiController]
[ApiVersion("1.0")]
public class BaseApiController : ControllerBase
{
}

Controller:

[Consumes("application/json")]
public class AuthController : BaseApiController
{
    private readonly ILogger<AuthController> _logger;
    private IAuthService _authService;

    public AuthController(ILogger<AuthController> logger, IAuthService authService)
    {
        _logger = logger;
        _authService = authService;
    }

    [HttpPost]
    [Route(ApiRoutes.Auth.SignIn)]
    public async Task<ActionResult<Response<LoginResponseDto>>> Login([FromBody] LoginRequestDto model)
    {
        var result = await _authService.Login(model);
        return StatusCode(result.StatusCode, result);
    }
}

ApiRoutes:

public static class ApiRoutes
{
    public const string Domain = "api";
    public const string Version = "v{version:apiVersion}";
    public const string Base = Domain + "/" + Version;

    public static class Auth
    {
        public const string SignIn = Base + "/login";
    }
}

IAuthService:

public interface IAuthService
{
    Task<Response<LoginResponseDto>> Login(LoginRequestDto loginDto);
}

AuthService:

using Serilog;

public class AuthService : IAuthService
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IMapper _mapper;
    private readonly ITokenGeneratorService _tokenGenerator;
    private readonly IUnitOfWork _unitOfWork;
    private readonly ILogger _logger;
    private readonly ITokenRepository _tokenRepository;

    public AuthService(UserManager<ApplicationUser> userManager, IUnitOfWork unitOfWork, ILogger logger,
        IMapper mapper, ITokenGeneratorService tokenGenerator, ITokenRepository tokenRepository)
    {
        _userManager = userManager;
        _mapper = mapper;
        _tokenGenerator = tokenGenerator;
        _unitOfWork = unitOfWork;
        _logger = logger;
        _tokenRepository = tokenRepository;
    }
    public async Task<Response<LoginResponseDto>> Login(LoginRequestDto model)
    {
        var response = new Response<LoginResponseDto>();
        _logger.Information("Login Attempt");
        var validityResult = await ValidateUser(model);

        if (!validityResult.Successful)
        {
            _logger.Error("Login operation failed");
            response.Message = validityResult.Message;
            response.StatusCode = validityResult.StatusCode;
            response.Successful = false;
            return response;
        }

        //var user = await _userManager.FindByEmailAsync(model.Email);
        var user = await _userManager.FindByEmailAsync(model.UserName);
        var roles = await _userManager.GetRolesAsync(user);
        var refreshToken = _tokenGenerator.GenerateRefreshToken();
        user.RefreshToken = refreshToken;
        user.RefreshTokenExpiryTime = DateTime.Now.AddDays(7); //sets refresh token for 7 days
        var result = new LoginResponseDto()
        {
            Token = await _tokenGenerator.GenerateToken(user),
            RefreshToken = refreshToken,
            User = _mapper.Map<UserDto>(user),
            Roles = roles,
            //expires = token.ValidTo
        };
        await _userManager.UpdateAsync(user);

        _logger.Information("User successfully logged in");
        response.StatusCode = (int)HttpStatusCode.OK;
        response.Message = "Login Successfully";
        response.Data = result;
        response.Successful = true;
        return response;
    }
}

ApplicationDbContext:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {
    }
    public DbSet<ApplicationUser> ApplicationUsers { get; set; }
    public DbSet<ApplicationRole> ApplicationRoles { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.ApplyConfigurationsFromAssembly(typeof(ApplicationDbContext).Assembly);
        base.OnModelCreating(builder);
    }
}

Sorry if my code is too much. I just want to show full detail. Finally in my code I have the program.cs that binds the services.

Program.cs:

var builder = WebApplication.CreateBuilder(args);
ConfigurationManager configuration = builder.Configuration;
var environment = builder.Environment;
var swaggerDocOptions = new SwaggerDocOptions();

// Add services to the container.
builder.Services.AddIdentity<ApplicationUser, ApplicationRole>(
    options =>
    {
        options.SignIn.RequireConfirmedAccount = false;
        options.User.RequireUniqueEmail = true;
        options.Password.RequireUppercase = false;
    }).AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.AddHttpContextAccessor();

builder.Services.AddMvc();
builder.Services.AddControllers().AddNewtonsoftJson(op => op.SerializerSettings.ReferenceLoopHandling
            = Newtonsoft.Json.ReferenceLoopHandling.Ignore); ;
// AutoMapper
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
// Authentication
builder.Services.AddAuthentication(configuration);
// Db Injection
builder.Services.AddDbContextAndConfigurations(environment, configuration);

// Swagger
builder.Services.AddSwaggerGen();
builder.Services.AddOptions<SwaggerGenOptions>()
    .Configure<IApiVersionDescriptionProvider>((swagger, service) =>
    {
        foreach (ApiVersionDescription description in service.ApiVersionDescriptions)
        {
            swagger.SwaggerDoc(description.GroupName, new OpenApiInfo
            {
                Title = swaggerDocOptions.Title,
                Version = description.ApiVersion.ToString(),
                Description = swaggerDocOptions.Description,
                TermsOfService = new Uri("https://ddddd.com/LICENSE.md"),
                Contact = new OpenApiContact
                {
                    Name = swaggerDocOptions.Organization,
                    Email = swaggerDocOptions.Email
                },
                License = new OpenApiLicense
                {
                    Name = "MIT",
                    Url = new Uri("https://ddddd.com")
                }
            });
        }

        var security = new Dictionary<string, IEnumerable<string>>
        {
            {"Bearer", new string[0]}
        };

        swagger.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
        {
            Description = "JWT Authorization header using the Bearer scheme.",
            Name = "Authorization",
            In = ParameterLocation.Header,
            Type = SecuritySchemeType.ApiKey,
            Scheme = "Bearer",
            BearerFormat = "JWT"
        });

        swagger.OperationFilter<AuthorizeCheckOperationFilter>();

        var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        swagger.IncludeXmlComments(xmlPath);

    });
// Register and Configure API versioning
builder.Services.AddApiVersioning(options =>
{
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.ReportApiVersions = true;
});

// Register and configure API versioning explorer
builder.Services.AddVersionedApiExplorer(options =>
{
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl = true;

});


// DI
builder.Services.AddScoped<IAuthService, AuthService>();
builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
builder.Services.AddScoped<ITokenRepository, TokenRepository>();
builder.Services.AddScoped<ITokenGeneratorService, TokenGeneratorService>();
builder.Services.AddScoped<UserManager<ApplicationUser>>();
builder.Services.AddScoped<RoleManager<ApplicationRole>>();

builder.Logging.AddJsonConsole();
var app = builder.Build();
// Logging
ILogger logger = app.Logger;

// Seed At Start
using (var scope = app.Services.CreateScope())
{
    var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
    var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
    var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<ApplicationRole>>();
    try
    {
        await ApplicationSeeder.SeedData(context, userManager, roleManager);
    }
    catch (Exception ex)
    {
        logger.LogError(ex, "An error occured while attempting to create DB");
    }
}

// Configure the HTTP request pipeline.
app.UseSwagger();
app.UseSwaggerUI();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseHsts();
app.UseCors(x => x
        .AllowAnyOrigin()
        .AllowAnyMethod()
        .AllowAnyHeader());
app.MapControllers();
string? port = Environment.GetEnvironmentVariable("PORT");
if (!string.IsNullOrWhiteSpace(port))
{
    app.Urls.Add("http://*:" + port);
}
app.Run();

I used AutoMapper and Serilog.

When I tried to Run the Application, I got this error:

System.AggregateException
  HResult=0x80131500
  Message=Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: IAuthService Lifetime: Scoped ImplementationType: AuthService': Unable to resolve service for type 'Serilog.ILogger' while attempting to activate 'AuthService'.)
  Source=Microsoft.Extensions.DependencyInjection
  StackTrace:
   at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1 serviceDescriptors, ServiceProviderOptions options)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
   at Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory.CreateServiceProvider(IServiceCollection containerBuilder)
   at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()
   at Program.<<Main>$>d__0.MoveNext() in C:\Trustedpath\Zenith_Projects\ManagedAccount\ZMA-App\ZMA.WebApi\Program.cs:line 136

  This exception was originally thrown at this call stack:
    [External Code]

Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: IAuthService Lifetime: Scoped ImplementationType: AuthService': Unable to resolve service for type 'Serilog.ILogger' while attempting to activate 'AuthService'.

Inner Exception 2:
InvalidOperationException: Unable to resolve service for type 'Serilog.ILogger' while attempting to activate 'AuthService'.

I added this to Program.cs:

var logger = new LoggerConfiguration()
    .ReadFrom.Configuration(builder.Configuration)
    .Enrich.FromLogContext()
    .CreateLogger();
builder.Logging.ClearProviders();
builder.Logging.AddSerilog(logger);

var app = builder.Build();

and this to appsettings:

  "Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "Microsoft.Hosting.Lifetime": "Information"
      }
    },
    "Filter": [
      {
        "Name": "ByExcluding",
        "Args": { "expression": "@mt = 'An unhandled exception has occurred while executing the request.'" }
      }
    ],
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          //"path": "./logs/log-.txt",
          "path": "../logs/webapi-.log",
          "rollingInterval": "Day",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Username}{Message:lj}{NewLine}{Exception}"
        }
      },
      {
        "Name": "Seq",
        "Args": { "serverUrl": "http://localhost:5341" }
      }
    ]
  },

But the error is still there.

How do I resolve it?

Thanks

Unable to resolve service for type 'Serilog.ILogger' while attempting to activate 'AuthService' means exactly what it means. You need to register ILogger in your IOC Container, please follow the detailled steps on https://github.com/serilog/serilog-aspnetcore

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM