ApiExplorer: How to Change The Default for IgnoreApi

≡放荡痞女 提交于 2021-01-07 02:58:27

问题


We have a couple of ApiController implementations and we do not want most operations to be included in the metadata of ApiExplorer.

By default, if you do not add [ApiExplorerSettings(IgnoreApi = true)] to your operation, it will be added so this means the default is false.

This probably due to IgnoreApi being a boolean and defaulting to false but how can I change this default to true without having to override ApiExplorerSettings?

This is a basic WebApi implementation without using MVC components.

I tried looking around for simple config based solutions or examples of ApiExplorerSettings usage but none have really worked out for me.

The closest to what I want is: DotNetCore - is ApiExplorer supported, and how to use it?; however, it focuses on 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!";
        }
    }

I want to be able to just use ApiExplorerSettings on operations which I want to use instead of marking the ones I do not want to use.


回答1:


you can the IDocumentFilter interface to achieve it:

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

in Startup.cs -> ConfigureServices use the filter:

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



回答2:


For those who are interested, I ended up overriding the ApiExplorer class to override the ShouldExploreAction and ShouldExploreController methods. I reversed the boolean logic there and it works as requested.

[Edited with example as this was requested]

You can do the following:

Make a class that overrides from 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;
        }
    }
}

Use custom class in WebApiConfig

In the WebApiConfig.cs file you can overide the IApiExplorer service instance by placing the following line in the Register(HttpConfiguration config) method.

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


来源:https://stackoverflow.com/questions/55830502/apiexplorer-how-to-change-the-default-for-ignoreapi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!