在控制台应用程序中调用 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
.
时,上述解决方案不起作用
在一个解决方案中,我有一个 .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
.