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(使用 ConfigureServices
和 Configure
方法),也许是您以前的大部分应用程序。
为此,在您的 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
模式或其任何特征,例如 IApplicationBuilder
或 IWebHostEnvironment
.
不久前,有人问我们是否可以弄清楚如何在不使用 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).
我正在将 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(使用 ConfigureServices
和 Configure
方法),也许是您以前的大部分应用程序。
为此,在您的 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
模式或其任何特征,例如 IApplicationBuilder
或 IWebHostEnvironment
.
不久前,有人问我们是否可以弄清楚如何在不使用 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).