从 class 库注册 Web API 控制器

register Web API controller from class library

我有一个 .NET Core 工作项目,想要添加一个提供多个 HTTP 端点的库。 我必须留在 worker 项目中,我无法将其更改为 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();
    }
}

.

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

    public void Configure(IApplicationBuilder applicationBuilder)
    {
        applicationBuilder.AddLibrary();
    }
}

.

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>();
            });
}

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

我可以 但我无法将 Web 控制器添加到库项目并从库中调用它们。

我的电脑上有一个可行的解决方案。

解决问题

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

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

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;
    }
}

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

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

你不需要的东西

  1. 您不需要在 IServiceCollectionExtensions 中调用 services.AddMvc()。不带参数的调用是 same as calling AddControllersWithViews() and AddRazorPages().
  2. 您的库项目中不需要 Microsoft.AspNetCore.Mvc.Core 包 - 我的仅使用您添加的框架引用即可正常运行。我那里唯一的包裹是 Microsoft.AspNetCore.Server.Kestrel.Core.