【问题标题】:ASP.NET Core Web API - Some services are not able to be constructed (Error while validating the service descriptorASP.NET Core Web API - 无法构建某些服务(验证服务描述符时出错
【发布时间】:2023-02-03 18:36:28
【问题描述】:

在 ASP.NET Core-6 Web API 应用程序中,我正在实施 MailKit。所以我有这段代码:

我在实用程序中有这个。

电子邮件配置:

public class EmailConfigurations
{
    public string SmtpHost { get; set; }
    public string SenderName { get; set; }
    public string SenderEmail { get; set; }
    public int SmtpPort { get; set; }
    public string Username { get; set; }
    public string Password { get; set; } 
}

然后是服务。

邮件服务:

public class MailService : IMailService
{
    private readonly ILogger _logger;
    private readonly EmailConfigurations _emailConfig;
    public MailService(
        ILogger logger,
        EmailConfigurations emailConfig
        )
    {
        _logger = logger;
        _emailConfig = emailConfig;
    }

    public async Task<bool> SendEmailAsync(MailRequest mailRequest)
    {
        var email = new MimeMessage { Sender = MailboxAddress.Parse(_emailConfig.SenderEmail) };
        email.To.Add(MailboxAddress.Parse(mailRequest.ToEmail));
        email.Subject = mailRequest.Subject;
        var builder = new BodyBuilder();
        if (mailRequest.Attachments != null)
        {
            foreach (var file in mailRequest.Attachments.Where(file => file.Length > 0))
            {
                byte[] fileBytes;
                await using (var ms = new MemoryStream())
                {
                    file.CopyTo(ms);
                    fileBytes = ms.ToArray();
                }
                builder.Attachments.Add((file.FileName + Guid.NewGuid().ToString()), fileBytes, ContentType.Parse(file.ContentType));
            }
        }

        builder.HtmlBody = mailRequest.Body;
        email.Body = builder.ToMessageBody();
        try
        {
            using var smtp = new SmtpClient();
            smtp.Connect(_emailConfig.SmtpHost, _emailConfig.SmtpPort, MailKit.Security.SecureSocketOptions.None);
            smtp.AuthenticationMechanisms.Remove("XOAUTH2");
            smtp.CheckCertificateRevocation = false;
            await smtp.SendAsync(email);
            smtp.Disconnect(true);
            return true;
        }
        catch (Exception e)
        {
            _logger.Error(e, e.Source, e.InnerException, e.Message, e.ToString());
            return false;
        }
    }
}

电子邮件发件人:

public class EmailSender : IEmailSender
{
    private readonly EmailConfigurations _emailConfig;
    private readonly ILogger _logger;

    public EmailSender(
        EmailConfigurations emailConfig,
        ILogger logger
        )
    {
        _emailConfig = emailConfig;
        _logger = logger;
    }

    public void SendEmail(Message message)
    {
        var emailMessage = CreateEmailMessage(message);

        Send(emailMessage);
    }

    public async Task SendEmailAsync(Message message)
    {
        var mailMessage = CreateEmailMessage(message);

        await SendAsync(mailMessage);
    }

    private MimeMessage CreateEmailMessage(Message message)
    {
        var emailMessage = new MimeMessage();
        emailMessage.From.Add(new MailboxAddress(_emailConfig.SenderEmail));
        emailMessage.To.AddRange(message.To);
        emailMessage.Subject = message.Subject;

        var bodyBuilder = new BodyBuilder { HtmlBody = string.Format("<h2 style='color:red;'>{0}</h2>", message.Content) };

        if (message.Attachments != null && message.Attachments.Any())
        {
            byte[] fileBytes;
            foreach (var attachment in message.Attachments)
            {
                using (var ms = new MemoryStream())
                {
                    attachment.CopyTo(ms);
                    fileBytes = ms.ToArray();
                }

                bodyBuilder.Attachments.Add(attachment.FileName, fileBytes, ContentType.Parse(attachment.ContentType));
            }
        }

        emailMessage.Body = bodyBuilder.ToMessageBody();
        return emailMessage;
    }

    private void Send(MimeMessage mailMessage)
    {
        using (var client = new SmtpClient())
        {
            try
            {
                client.Connect(_emailConfig.SmtpHost, _emailConfig.SmtpPort, MailKit.Security.SecureSocketOptions.None);
                client.AuthenticationMechanisms.Remove("XOAUTH2");
                client.CheckCertificateRevocation = false;
                client.Send(mailMessage);
            }
            catch (Exception ex)
            {
                _logger.Information(JsonConvert.SerializeObject(ex));
                throw;
            }
            finally
            {
                client.Disconnect(true);
                client.Dispose();
            }
        }
    }

    private async Task SendAsync(MimeMessage mailMessage)
    {
        using (var client = new SmtpClient())
        {
            try
            {
                //  client.Connect(_emailConfig.SmtpHost, _emailConfig.SmtpPort, true);
                client.Connect(_emailConfig.SmtpHost, _emailConfig.SmtpPort, MailKit.Security.SecureSocketOptions.None);
                client.AuthenticationMechanisms.Remove("XOAUTH2");
                // client.Authenticate(_emailConfig.Username, _emailConfig.Password);
                client.CheckCertificateRevocation = false;

                await client.SendAsync(mailMessage);
            }
            catch (Exception ex)
            {
                _logger.Information(JsonConvert.SerializeObject(ex));
                throw;
            }
            finally
            {
                await client.DisconnectAsync(true);
                client.Dispose();
            }
        }
    }
}

然后我有依赖注入。

public static class DIServiceExtension
{
    public static void AddDependencyInjection(this IServiceCollection services)
    {
        // Add Service Injections Here
        services.AddScoped<IAuthService, AuthService>();
        services.AddScoped<ITokenGeneratorService, TokenGeneratorService>();
        services.AddScoped<ITokenRepository, TokenRepository>();
        services.AddTransient<IMailService, MailService>();
        services.AddScoped<IEmailSender, EmailSender>();
    }
}

程序.cs:

// Register Dependency Injection Service Extension
builder.Services.AddDependencyInjection();

var app = builder.Build();

但是我得到了这个错误:

System.AggregateException
  HResult=0x80131500
  Message=Some services are not able to be constructed (Error while validating the service descriptor 
'ServiceType: Lms.Application.Services.Abstract.IEmailSender Lifetime: Scoped ImplementationType: 
Lms.Application.Services.Concrete.EmailSender': Unable to resolve service for type 
'Lms.Application.Utilities.v1.Common.EmailConfigurations' while attempting to activate 'Lms.Application.Services.Concrete.EmailSender'.)
  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:\Lms.WebApi\Program.cs:line 172
   at Program.<Main>(String[] args)

  This exception was originally thrown at this call stack:
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(System.Type, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain, System.Reflection.ParameterInfo[], bool)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Microsoft.Extensions.DependencyInjection.ServiceLookup.ResultCache, System.Type, System.Type, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Microsoft.Extensions.DependencyInjection.ServiceDescriptor, System.Type, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain, int)
    Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite(Microsoft.Extensions.DependencyInjection.ServiceDescriptor, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain)
    Microsoft.Extensions.DependencyInjection.ServiceProvider.ValidateService(Microsoft.Extensions.DependencyInjection.ServiceDescriptor)

Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: Lms.Application.Services.Abstract.IMailService Lifetime: Transient ImplementationType: Lms.Application.Services.Concrete.MailService': Unable to resolve service for type 'Lms.Application.Utilities.v1.Common.EmailConfigurations' while attempting to activate 'Lms.Application.Services.Concrete.MailService'.

Inner Exception 2:
InvalidOperationException: Unable to resolve service for type 'Lms.Application.Utilities.v1.Common.EmailConfigurations' while attempting to activate 'Lms.Application.Services.Concrete.MailService'.

C:\Lms.WebApi\Program.cs: 第 172 行

是

var app = builder.Build();

我哪里弄错了,我该如何解决?

【问题讨论】:

  • 您忘记将 EmailConfigurations 注册为依赖项。
  • 该错误提示您忘记注册EmailConfigurations。这是从哪里来的?它是如何填充的?使用硬编码值?从配置设置?如果它来自配置部分,您需要 builder.Services.Configure&lt;EmailConfigurations&gt;(thatSection) 或 thatSection.Get&lt;EmailConfigurations&gt; 某处才能从设置中创建它

标签: c# asp.net-core asp.net-web-api


【解决方案1】:

如评论中所述,您没有将 EmailConfigurations 注册为依赖项。

假设您正在从中提取价值应用设置.json如下:

{
  "EmailConfigurations": {
    "SmtpHost": "Value of SmtpHost",
    "SenderName": "Value of SenderName",
    // Other properties
  }
}
  1. 将配置值绑定到EmailConfigurations类。
    builder.Services.Configure<EmailConfigurations>(
        builder.Configuration.GetSection("EmailConfigurations"));
    
    1. 在MailService中,使用IOptions&lt;EmailConfigurations&gt;获取EmailConfigurations的注入依赖及其值。
    public class MailService : IMailService
    {
        private readonly ILogger _logger;
        private readonly EmailConfigurations _emailConfig;
        public MailService(
            ILogger logger,
            IOption<EmailConfigurations> emailConfigOption
            )
        {
            _logger = logger;
            _emailConfig = emailConfigOption.Value;
        }
    
        ...
    
    }
    
    1. 同样转到EmailSender,按照步骤2个.
    public class EmailSender : IEmailSender
    {
        private readonly EmailConfigurations _emailConfig;
        private readonly ILogger _logger;
    
        public EmailSender(
            IOption<EmailConfigurations> emailConfigOption,
            ILogger logger
            )
        {
            _emailConfig = emailConfigOption.Value;
            _logger = logger;
        }
    
        ...
    }
    

    参考:Bind hierarchical configuration data using the options pattern

【讨论】:

    猜你喜欢
    • 2020-06-04
    • 2021-11-10
    • 2022-06-28
    • 2021-07-09
    • 1970-01-01
    • 2023-03-08
    • 2021-06-06
    • 1970-01-01
    • 2021-02-27
    相关资源
    最近更新 更多