【问题标题】:Hosting Web API in .Net Core Worker Service - cannot reference IWebHostEnvironment在 .Net Core Worker 服务中托管 Web API - 无法引用 IWebHostEnvironment
【发布时间】:2019-10-07 17:53:45
【问题描述】:

我正在创建一个 .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 包中,但引用它似乎不起作用。

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

【问题讨论】:

  • 如果您的目标是 dotnet core 3.0,您应该完全删除 &lt;PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" /&gt;&lt;PackageReference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.2.0" /&gt; 行。推荐阅读Migrate from ASP.NET Core 2.2 to 3.0

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


【解决方案1】:

将服务添加到 API 项目要容易得多。这只是额外的一行。

如果您不能或不想重新开始,请手动更改您的项目。忘记IWebHostBuilder,它现在已经过时或不推荐使用了。

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

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

【讨论】:

  • 是的,这行得通,谢谢!但是,由于似乎是 nuget / 包版本问题,向使用 Worker Service 模板创建的项目添加 Web api 支持 仍然让我感到困扰(或其他我不明白的东西)。我可以阅读的对文档的任何建议可以解释为什么添加一个包含正确类型和方法的 nuget 包(似乎)仍然不允许我使用这些 API?
  • 也可以通过编辑worker_service模板的csproj文件来完成:
【解决方案2】:

我研究了很多,我使用了一些格式不正确且缺乏性能的新方法来解决这个问题,我试图找到解决这个问题的正确方法,最后,我解决了它并分享了我的在这篇文章中的经验。您可以使用以下 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服务主文件,继承自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!");
                });
            });
        }
    }
}

启动文件是你的网络服务器文件,它启动一个主机并有一个简单的 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>();
                });

【讨论】:

  • 在 net5.0 中 UseWindowsService() 不再是 IHostBuilder 中的方法。还有其他想法吗?
  • 从 NuGet 安装“Microsoft.Extensions.Hosting.WindowsServices”包,然后更新所有现有包。所以你可以使用 UseWindowsService() 方法。
  • dotnet 添加 PROJECT_NAME 包 Microsoft.Extensions.Hosting.WindowsServices
  • 我正在使用它并且它可以工作,但是你如何将它与控制器连接起来?当我在 app.UseEndpoints 中添加 MapControllers 并在 ConfigureServices 中调用 AddControllers 时,它找不到控制器。我从示例 rest api 中复制了虚拟 WeatherForecastController 但它没有找到它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
相关资源
最近更新 更多