【问题标题】:ApiExplorer: How to Change The Default for IgnoreApiApiExplorer:如何更改 IgnoreApi 的默认值
【发布时间】:2019-04-24 12:52:01
【问题描述】:

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

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

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

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

我尝试寻找基于简单配置的解决方案或ApiExplorerSettings 用法示例,但没有一个真正适合我。

最接近我想要的是: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,而不是标记我不想使用的操作。

【问题讨论】:

  • 一个选项:创建一个常量。将属性值设置为该常量。
  • @Amy 这可行,但我们想使用或重用已经是 .NET 框架一部分的东西。
  • 常量已经是语言的一部分......

标签: c# asp.net-web-api asp.net-apicontroller


【解决方案1】:

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

[根据要求编辑示例]

您可以执行以下操作:

创建一个从 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 中使用自定义类

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

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

【讨论】:

  • 你能举个例子吗?
  • @ChrisGonzales 重现应该不难,但我还是添加了一个示例。
  • 我可能在这里做错了,但您的答案中使用的 ApiExplorer 类型似乎不再可继承(或至少在 ASP.NET 5+ 中不可继承)
  • @thebugsdontwork 我不完全确定我当时使用的是哪个版本,但我只能说 ApiExplorer 是 System.Web.Http.Description 命名空间的一部分。也许随着时间的推移它已被弃用或更改。
【解决方案2】:

你可以通过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
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 2022-12-04
    • 1970-01-01
    • 1970-01-01
    • 2019-07-05
    • 2021-12-19
    相关资源
    最近更新 更多