在控制台应用程序中调用 C# web API 服务

Call a C# web API service in a console application

在一个解决方案中,我有一个 .net 5 ASP.NET Core Web API,其中包含一个接口 IEmailSender 和相应的 EmailSender 实现,以及一个控制台应用程序项目。 在控制台应用程序中,我创建了一个派生的计划服务,在 catch 块中,我想使用 EmailSender 发送一封电子邮件,其中包含系统中抛出的错误的详细信息。

public StockOpeningValuesUpdateScheduledService(IScheduleConfig<StockOpeningValuesUpdateScheduledService> config, IHttpClientFactory factory, IServiceProvider serviceProvider)
            : base(config.CronExpression, config.TimeZoneInfo, serviceProvider)
        {
            _factory = factory;
            _serviceProvider = serviceProvider;
        }

        public override async Task DoWork(CancellationToken cancellationToken = default)
        {
            try
            {
                var client = _factory.CreateClient("trading");

                await client.PostAsync("company-buyable-shares/update-opening-values", null, cancellationToken);
            }
            catch (Exception ex)
            {
                using var serviceScope = _serviceProvider.CreateScope();

                var emailSender = serviceScope.ServiceProvider.GetRequiredService<IEmailSender>();

                await emailSender.SendAbnormalEventEmailAsync(ex);
            }
        }

我在控制台应用程序的 Program.cs 中调用计划服务,并尝试将 EmailSender 注册为作用域服务。

public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureServices((_, services) =>
            {
                services.AddHttpClient("trading", client =>
                    client.BaseAddress = new Uri("https://localhost:44395"));

                services.AddScoped<IEmailSender, EmailSender>()
                .AddScheduledService<StockOpeningValuesUpdateScheduledService>(service =>
                {
                    service.CronExpression = "*/2 * * * *";
                    service.TimeZoneInfo = TimeZoneInfo.Utc;
                });            
            });

当我在控制台应用程序中模拟错误时(为了收到有关它的电子邮件) 我得到一个例外

System.InvalidOperationException: 'Unable to resolve service for type 'StockTradingSimulator.BusinessLayer.Services.IEmailService' while attempting to activate 'StockTradingSimulator.BusinessLayer.Helpers.EmailSender'.

在网络中 API 我在上面的 catch 块中有一个设置,用于另一个调用范围服务方法的派生计划服务。此功能正在运行,可能是因为计划服务、作用域服务及其接口在同一个项目中。

有人知道如何在我的控制台应用程序中成功注册和调用 EmailSender 吗?

谢谢。

问题是 EmailSender 有未解决的依赖项。没有解决的依赖是IEmailService

您发布的代码和描述没有参考导致错误的接口。 IEmailService 的实现在哪里?

构建 IServiceProvider 时,需要将 IEmailService 添加到 DI 容器。类似于:

services.AddScoped<IEmailService, MyEmailService>();

到控制台应用程序的 Program.cs 我添加了 EmailSender 的所有依赖项以及访问我的网站 appsettings.json 文件的 AppSettings 部分的方法 API,其中包含 SMTP 详细信息 EmailService 通过 IOptions<AppSettings> appSettings.

的依赖注入使用
public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .ConfigureServices((_, services) =>
            {
                var configuration = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json", false)
                    .Build();

                services.AddHttpClient("trading", client =>
                    client.BaseAddress = new Uri("https://localhost:44395"));

                services.AddSingleton(configuration)
                .Configure<AppSettings>(configuration.GetSection("AppSettings"))
                .AddScoped<IEmailSender, EmailSender>()
                .AddScoped<IEmailService, EmailService>()
                .AddDbContext<TradingDbContext>()
                .AddAutoMapper(typeof(BusinessLayerServiceCollectionExtensions).Assembly)
                .AddScheduledService<StockOpeningValuesUpdateScheduledService>(service =>
                {
                    service.CronExpression = "*/1 * * * *";
                    service.TimeZoneInfo = TimeZoneInfo.Utc;
                });           
            });

更新: 从控制台应用程序访问 appsettings.json 的正确方法已在 here 中描述。当控制台应用程序为 运行 且 dotnet run.

时,上述解决方案不起作用