在.Net Core Worker Service中托管Web API-无法引用IWebHostEnvironment

时间:2019-10-07 17:53:45

标签: asp.net-core .net-core

我正在创建.NET Core Worker服务,并希望公开该服务的ASP.Net Core Web API。我正在使用.NET Core 3.0。 最初,我的计划是用IWebHostBuilder替换IHostBuilder并添加一个Startup类,就像常规的Asp.Net Core Web应用程序一样(不过这可能过于简化了)。

我的计划是尝试替换

public static IHostBuilder CreateHostBuilder(string[] args)
        {
            return Host.CreateDefaultBuilder(args)                
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<Worker>();
                });
        }

使用

public static IWebHostBuilder CreateHostBuilder(string[] args)
        {
            return WebHost.CreateDefaultBuilder(args)
                .ConfigureServices(services =>
                {
                    services.AddHostedService<Worker>();
                }).UseStartup<Startup>();            
        }

这可能根本不起作用,但至少这是一个起点... 使我无法尝试这种方法的原因是,我无法实现Startup类,因为IWebHostEnvironment不可用。

这是我的

<PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <UserSecretsId>dotnet-WorkerServices-0E977A2C-F0C8-49E7-B00A-5EB01B99FBEB</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" />
    <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.0.0" />
  </ItemGroup>

据我所知,IWebHostEnvironment应该在Microsoft.Extensions.Hosting.Abstractions nuget包中,但是引用它似乎无效。

有人有什么想法吗? -谢谢!

2 个答案:

答案 0 :(得分:3)

我研究了很多,我使用了一些格式不正确且缺乏性能的新方法来解决这个问题,我试图找到解决这个问题的正确方法,最后,我解决了它并分享了我的在这篇文章中的经验。您可以使用以下 100% 有效的步骤,此外,您还可以从我的 GitHub 个人资料中克隆 Worker-Service Web-API 模板。

实际上,您不需要使用 IWebHostBuilder。以下步骤足以在 .net 核心工作服务中自托管 WebAPI,并在 Windows 服务中托管工作服务:

  1. 创建一个简单的控制台应用程序。
  2. 在控制台应用程序中使用 NuGet 安装包“Microsoft.AspNetCore.App”和“Microsoft.Extensions.Hosting.WindowsServices”。
  3. 创建一个名为 Worker.cs 的空文件并将以下代码放入其中:
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace WorkerServiceWebAppTemplate
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;

        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}

上面的类是你的worker service主文件,继承自BackgroundService,我个人大部分时间都是继承IHostedService。

  1. 创建另一个名为 Startup.cs 的文件并输入以下代码行:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;

namespace WorkerServiceWebAppTemplate
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
                app.UseDeveloperExceptionPage();
            else
                app.UseHsts();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });
        }
    }
}

启动文件是您的 Web 服务器文件,它启动一个主机并有一个简单的 GET API (/) 返回一个简单的消息,您可以对其进行扩展。

  1. 最后,您必须同时启动工作服务和主机。像以下代码一样更改您的 Program.cs:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

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

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

Program.cs 文件中的以下几行很神奇:

                .UseWindowsService()
                .ConfigureServices((hostBuilderContext, services) =>
                {
                    services.AddHostedService<Worker>();
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

答案 1 :(得分:0)

向API项目添加服务要容易得多。那只是一条额外的线。

如果您不能或不想重新开始,请手动更改项目。忘掉IWebHostBuilder,它已经过时或过时了。

我可以在这里发布一些片段,但要容易得多:创建一个临时API项目,复制Program和Startup类(但保留您的名称空间),然后在Startup内部:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHostedService<Worker>();  // the worker will run
    services.AddControllers();
}