从类库注册 Web API 控制器

Ola*_*son 9 c# kestrel asp.net-core-mvc .net-core

我有一个 .NET Core worker 项目,想添加一个提供多个 HTTP 端点的库。我必须留在工作人员项目中,我无法将其更改为 Web API 项目。到目前为止我做了什么:

  • 我创建了一个工人项目
  • 我创建了一个库项目
  • 我在 worker 项目中添加了对库的引用
  • Worker.csprojLib.csproj 中,我添加<FrameworkReference Include="Microsoft.AspNetCore.App" />到项目组以访问 webbuilder 的东西
  • 我在库项目中安装了包Microsoft.AspNetCore.Mvc.Core
  • 在库项目中,我添加了几个扩展类和一个 Web API 控制器用于测试目的

.

public static class IApplicationBuilderExtensions
{
    public static IApplicationBuilder AddLibrary(this IApplicationBuilder applicationBuilder)
    {
        applicationBuilder.UseRouting();
        applicationBuilder.UseEndpoints(endpoints => { endpoints.MapControllers(); });
        return applicationBuilder;
    }
}

public static class IServiceCollectionExtensions
{
    public static IServiceCollection AddLibrary(this IServiceCollection services)
    {
        services.AddMvc(); // this might be not needed
        services.AddControllers();
        return services;
    }
}

public static class KestrelServerOptionsExtensions
{
    public static void AddLibrary(this KestrelServerOptions kestrelServerOptions)
    {
        kestrelServerOptions.ListenLocalhost(5000); // value from config
    }
}

[ApiController]
[Route("[controller]")]
public class UsersController : ControllerBase
{
    [HttpGet]
    public async Task<ActionResult> Test()
    {
        return Ok();
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 在工人项目中,我创建了一个Startup

.

internal class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddLibrary();
    }

    public void Configure(IApplicationBuilder applicationBuilder)
    {
        applicationBuilder.AddLibrary();
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 在工人项目中,我将Program课程修改为

.

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

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webHostBuilder =>
            {
                webHostBuilder.UseKestrel(kestrelServerOptions =>
                {
                    kestrelServerOptions.AddLibrary();
                }).UseStartup<Startup>();
            })
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
            });
}
Run Code Online (Sandbox Code Playgroud)
  • 我运行该项目并调用GET http://localhost:5000/users
  • 我希望得到 200 但得到 404 并且调试器没有命中库项目中的控制器端点

有人知道我错过了什么吗?

我可以将 Web API 控制器端点添加到 Kestrel 工作器项目,但我无法将 Web 控制器添加到库项目并从库中调用它们。

Joh*_*n H 9

我的计算机上有一个有效的解决方案。

解决问题

事实证明它实际上非常简单。MVCApplicationPart从不同的程序集中加载。在正常的 Web 应用程序设置中,即使使用 Razor 类库,这似乎也能正确拾取。但是,当使用辅助服务和库或 Razor 类库时,它不起作用,因此控制器的路由未注册。

要将库添加为应用程序部分,请打开IServiceCollectionExtensions您创建的类,并将其更改为:

public static class IServiceCollectionExtensions
{
    public static IServiceCollection AddLibrary(this IServiceCollection services)
    {
        services
            .AddControllers()
            // Notice the assembly is the type of this class, as this
            // is the assembly the controller is in.
            // You'll have to call this for every assembly you have
            // controllers in, except for any controllers
            // you might put in your worker service project.
            .AddApplicationPart(typeof(IServiceCollectionExtensions).Assembly);

        return services;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,启动应用程序并向其发送请求就http://localhost:5000/users可以了。我已经确认这适用于库和 Razor 类库。

工人服务路由

我还应该说,工作人员服务项目本身中的控制器将正常工作 - 这些不需要特殊的设置。

你不需要的东西

  1. 您不需要调用services.AddMvc()in IServiceCollectionExtensions。不带参数调用此方法与调用AddControllersWithViews()andAddRazorPages()相同。
  2. 您的库项目中不需要该Microsoft.AspNetCore.Mvc.Core包 - 我的项目只需使用您添加的框架引用即可正常运行。我那里唯一的包裹是Microsoft.AspNetCore.Server.Kestrel.Core.