ASP.NET Worker Service 中的核心不调用 Configure IApplicationBuilder

ASP.NET Core in a Worker Service doesn't call Configure IApplicationBuilder

我正在将 ASP.NET 核心应用程序 迁移到 Worker Service 模板,并打算保留 Startup 代码。 然而

Program 中,我保留了 CreateHostBuilder,如 MS 文档所述:

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseWindowsService()
        .ConfigureWebHostDefaults(
            webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            })
        .ConfigureServices(
            services =>
            {
                services.AddHostedService<Worker>();
            });

调试时,正在调用 ConfigureServices

public void ConfigureServices(IServiceCollection services)

但未达到/调用 Startup 中的 Configure

public void Configure(IApplicationBuilder app)

在调用 Run().

崩溃之前

我也试过同样的结果:

public static IHostBuilder CreateHostBuilder(string[] args)
    => Host.CreateDefaultBuilder(args)
        .UseWindowsService()
        .ConfigureWebHostDefaults(webBuilder => webBuilder.Configure(Startup.Configure))
        .ConfigureServices(
            services =>
            {
                Startup.ConfigureServices(services);
                services.AddHostedService<Worker>();
            });

有趣的部分是下面的代码实际上调用了 Startup.Configure(IApplicationBuilder app):

public static IHostBuilder CreateHostBuilder(string[] args)
    => Host.CreateDefaultBuilder(args)
        .UseWindowsService()
        .ConfigureWebHostDefaults(webBuilder => webBuilder.Configure(Startup.Configure));

只要我添加 ConfigureServices 它就会跳过 IApplicationBuilder 配置调用。

我是不是遗漏了什么或者建议的方法是什么?

编辑:

准确的错误是:

InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Builder.IApplicationBuilder' while attempting to activate 'Kledex.Extensions.KledexAppBuilder'.

堆栈跟踪:

at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(IEnumerable'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()

错误一到达 CreateHostBuilder(args).Build().Run(); 并尝试解析已注册的服务,而上面的服务依赖于 Startup.Configure() 方法中的某些配置 app.UseSomething();

Startup.Configure() 中的断点未命中。

您可以将 HostedService 的配置从程序 class 移动到启动。只需在调用 AddControllers 之前将此添加到 ConfigureServices 方法:

services.AddHostedService<Worker>();

我以这种方式将 HostedService 包括在我的项目中并且它有效。

这是我的标准 CreateHostBuilder:

public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });

是的,我遇到了同样的问题。

我们可以在 Microsoft 文档中找到问题的答案 here

我们需要为主机服务使用方法 ConfigureAppConfiguration

请查看我的代码示例。我们使用这段代码,它工作正常:


Program.cs:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseWindowsService()
            .ConfigureAppConfiguration((context, builder) =>
            {
                var environment = context.HostingEnvironment.EnvironmentName;
                builder.AddAppSettings(environment);
            })
            .ConfigureWebHostDefaults(builder =>
            {
                builder.UseStartup<Startup>();
            });
}

HostedService

public class HostedService : IHostedService
{
    private readonly IServiceScopeFactory _serviceScopeFactory;
    private readonly ILogger<HostedService> _logger;

    public HostedService(IServiceScopeFactory serviceScopeFactory, ILogger<HostedService> logger)
    {
        _serviceScopeFactory = serviceScopeFactory;
        _logger = logger;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Service is starting...");

        // Run new task and use your business logic
        using (var scope = _serviceScopeFactory.CreateScope())
        {
            // Resolve business manager class with many dependencies. It is Scoped LifeTime.
            var manager = scope.ServiceProvider.GetRequiredService<IClientManager>();
        }

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Service is stopping...");
        return Task.CompletedTask;
    }
}


所以我们使用这种方法只有一个麻烦,我们只能将单例注入 HostedService class。我们将注入 IServiceScopeFactory 到构造函数。然后我们创建范围,解决所有需要的依赖关系和 运行 我们的业务逻辑。

鉴于您正在尝试配置 Web 主机默认值并使用 ASP.NET Core 功能,例如 IApplicationBuilder我相信您打算 运行 服务某种网络服务器。这是正确的吗?

如果是这样,除了其他好的建议,我还有一个建议,那就是继续使用 ASP.NET Core 应用程序 - 显然启用 Startup 几乎 as is(使用 ConfigureServicesConfigure 方法),也许是您以前的大部分应用程序。

为此,在您的 Worker csproj 中,您可以将 <Project Sdk="Microsoft.NET.Sdk.Worker"> 替换为 <Project Sdk="Microsoft.NET.Sdk.Web">

然后,您可以配置您的 CreateHostBuilder 例如:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(
            webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

请注意,我故意删除了 UseWindowsService(),因为我描述的是使用 Worker services 的情况,而不是具体 Windows services.

现在您可以继续使用您的 Startup class,添加后台服务的注册:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        // ...
    }
    
    public void ConfigureServices(IServiceCollection services)
    {
        // ...
        services.AddHostedService<Worker>();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // ...
    }
}

希望这会有所帮助 :) 但是,如果您特别想开发 Windows services 而不是 Worker services,请告诉我们。

在这种情况下,我们一直拥有一个 ASP.NET 核心 WebApp/WebAPI 及其所有功能。我们刚刚为其添加了后台服务:)

这是你的问题:

您正在尝试使用专为 ASP.NET 核心设计的模式,但您没有使用 ASP.NET 核心,因此您没有获得 Startup 模式或其任何特征,例如 IApplicationBuilderIWebHostEnvironment.

不久前,有人问我们是否可以弄清楚如何在不使用 ASP.NET 核。 .

上面的答案没有给你Configure(IApplicationBuilder app, IWebHostEnvironment env)方法,也不应该。该方法专门用于网络主机。不是工人。 您没有理由需要此方法除非您正在启动 Web 主机。

如果是这样,那么您应该重新开始并创建一个全新的 ASP.NET 核心应用程序...不是 Worker。这会将您的应用程序配置为使用 Microsoft.NET.Sdk.Web SDK 而不是 Microsoft.NET.Sdk.Worker SDK,从而为您提供通过 Worker 路线丢失的功能。

除非您从 Worker SDK 转移到 ASP.NET 核心 SDK,否则您将不会 得到适合您的答案。也许有人会想出一些办法,但很可能是个混蛋。和kludges打破加班,是一个PITA来维持。

Microsoft.NET.Sdk.Web 用于 Windows 服务没有任何问题。微软甚至 shows you how (Specifically pay attention to Deployment Type section).