Reputation: 101
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.
Upvotes: 4
Views: 2472
Reputation: 101
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:
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;
}
}
}
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));
...
}
Upvotes: 1
Reputation: 138
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
});
Upvotes: 2