ApiExplorer:如何更改 IgnoreApi 的默认值

ApiExplorer: How to Change The Default for IgnoreApi

我们有几个 ApiController 实现,我们不希望大多数操作包含在 ApiExplorer 的元数据中。

默认情况下,如果您不将 [ApiExplorerSettings(IgnoreApi = true)] 添加到您的操作中,则会添加它,因此这意味着默认值为 false。

这可能是因为 IgnoreApi 是一个布尔值并且默认为 false 但我如何才能将此默认值更改为 true 而不必覆盖 ApiExplorerSettings

这是不使用 MVC 组件的基本 WebApi 实现。

我试着四处寻找基于简单配置的解决方案或 ApiExplorerSettings 用法示例,但 none 对我来说真的很有效。

最接近我想要的是:DotNetCore - is ApiExplorer supported, and how to use it?;但是,它侧重于 MVC。

    // For example
    [RoutePrefix("api/test")]
    public class TestController : ApiController
    {
        [HttpGet]
        [Route("helloworld")]
        [ApiExplorerSettings(IgnoreApi = false)]
        public string HelloWorld() {
            return "Hello world!";
        }

        [HttpGet]
        [Route("goodbyeworld")]
        [ApiExplorerSettings(IgnoreApi = true)]
        public string HelloWorld() {
            return "Goodbye world!";
        }

        [HttpGet]
        [Route("hiworld")]
        [ApiExplorerSettings(IgnoreApi = true)]
        public string HelloWorld() {
            return "Hi world!";
        }

        [HttpGet]
        [Route("seeyaworld")]
        [ApiExplorerSettings(IgnoreApi = true)]
        public string HelloWorld() {
            return "See ya world!";
        }
    }

我希望能够只对我想使用的操作使用 ApiExplorerSettings,而不是标记我不想使用的操作。

对于那些感兴趣的人,我最终覆盖了 ApiExplorer class 以覆盖 ShouldExploreAction 和 ShouldExploreController 方法。我在那里反转了布尔逻辑,它按要求工作。

[根据要求使用示例进行编辑]

您可以执行以下操作:

制作一个 class 从 ApiExplorer

覆盖
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Description;
using System.Web.Http.Routing;

namespace WebApi.Api
{
    public class CustomApiExplorer : ApiExplorer
    {
        public CustomApiExplorer(HttpConfiguration configuration) : base(configuration)
        {
        }

        /// <summary>
        /// Determines whether the controller should be considered.
        /// </summary>
        /// <param name="controllerVariableValue">The controller route parameter value.</param>
        /// <param name="controllerDescriptor">The associated <see cref="HttpControllerDescriptor">controller descriptor</see>.</param>
        /// <param name="route">The associated <see cref="IHttpRoute">route</see>.</param>
        /// <returns>True if the controller should be explored; otherwise, false.</returns>
        public override bool ShouldExploreController(string controllerVariableValue, HttpControllerDescriptor controllerDescriptor, IHttpRoute route)
        {
            if (string.IsNullOrEmpty(controllerVariableValue) || controllerDescriptor == null || route == null)
            {
                throw new ArgumentException();
            }

            var setting = controllerDescriptor.GetCustomAttributes<ApiExplorerSettingsAttribute>().FirstOrDefault();

            // Basically you check if there is a setting used and if ignore is set to true or false. You can also check if the routing is as one would expect but that is a different discussion. With this the ApiExplorer changes its logic by only registering API's that actively state IgnoreApi = false.
            if (setting != null && !setting.IgnoreApi)
            {
                return true;
            }

            return false;
        }
    }
}

在 WebApiConfig

中使用自定义 class

在 WebApiConfig.cs 文件中,您可以通过在 Register(HttpConfiguration config) 方法中放置以下行来覆盖 IApiExplorer 服务实例。

public static void Register(HttpConfiguration config) {
    ...
    config.Services.Replace(typeof(IApiExplorer), new CustomApiExplorer(config));
    ...
}

可以通过IDocumentFilter接口来实现:

    public class ApiDocFilter : IDocumentFilter
    {
        public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
        {
            var pathsToRemove = swaggerDoc.Paths
                .Where(pathItem => !pathItem.Key.Contains("/api/"))
                .ToList();

            foreach (var item in pathsToRemove)
            {
                swaggerDoc.Paths.Remove(item.Key);
            }
        }
    }

在 Startup.cs -> ConfigureServices 使用过滤器:

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo {Title = "some API", Version = "v1"});
    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    c.IncludeXmlComments(xmlPath);
    c.DocumentFilter<ApiDocFilter>();//<-- use doc filter
});