在一个项目中扩展 API 完全公开引用的 API 但路由冲突

Extending API in one project fully exposes referenced API but routes clash

我正在尝试将 Core 2.1 WebAPI 项目拆分为两个,以便我们可以根据情况公开两个不同的 API。简化一下,我们有一个 API,我们希望所有只读 (GET) 请求都在一个 API 中,整个集合在另一个中("admin" API)。在项目中启用了 Swagger。

我复制了项目,重命名一个(命名空间等)并将两者添加到同一个解决方案中,然后在只读项目中注释掉所有非 GET 控制器方法,在只读项目中注释掉所有 GET 方法管理项目。然后我在管理项目中添加了对只读项目的引用。

运行 只读项目,swagger 页面正常,只是 GET。 运行 管理项目在 swagger 页面上给出了 500。有趣的是,在调试过程中,我发现从管理项目中删除所有控制器,只读项目中的底层 API 完全直接暴露出来并且看起来功能齐全 - 这不是我所期望的和潜在的安全问题对于任何不期待的人。

但是,我随后又添加了一个控制器并将其更改为从只读控制器之一继承,覆盖了祖先构造函数等 - 它仍然给出了 500。

基础class:

namespace InfoFeed.WebAPI.Features.Account
{
    /// <summary>
    /// Handle user account related tasks
    /// </summary>
    [Authorize]
    [Produces("application/json")]
    [Route("api/account")]
    public class AccountController : Controller
    {
        private readonly ILogger _log;
        protected readonly IMediator _mediator;

        public AccountController(ILogger<AccountController> log,
                                 IMediator mediator)
        {
            _log = log;
            _mediator = mediator;
        }

后裔 class:

namespace InfoFeedAdmin.WebAPI.Features.Account
{
    /// <summary>
    /// Handle user account related tasks
    /// </summary>
    [Authorize]
    [Produces("application/json")]
    [Route("api/account")]
    public class AccountAdminController 
        : InfoFeed.WebAPI.Features.Account.AccountController
    {
        public AccountAdminController(ILogger<AccountAdminController> log,
                                 IMediator mediator)
            : base(log, mediator)
        {
        }

我认为路由可能会导致冲突,所以我尝试将其更改为 [Route("api/admin/account")] - 只要没有冲突的方法签名,此方法就有效。但是,这意味着有两组路由暴露给相同的底层控制器方法。

POST /api/account/signin
GET /api/account/signout

POST /api/admin/account/signin
GET /api/admin/account/signout

有谁知道我如何隐藏(也许有选择地)来自祖先 class 的路由,以便只有我选择从后代 class 公开的路由是 visible/accessible?

干杯

默认情况下,MVC 将搜索依赖树并查找控制器(甚至在其他程序集中)。
您可以使用 application parts 来避免在特定程序集或位置中寻找控制器。

如果您的程序集包含您不想使用的控制器,请将其从 ApplicationPartManager 中删除:

services.AddMvc()
.ConfigureApplicationPartManager(apm =>
{
    var dependentLibrary = apm.ApplicationParts
        .FirstOrDefault(part => part.Name == "DependentLibrary");

    if (dependentLibrary != null)
    {
       p.ApplicationParts.Remove(dependentLibrary);
    }
})

Source: https://docs.microsoft.com/en-us/aspnet/core/mvc/advanced/app-parts?view=aspnetcore-2.1