#if DEBUG using System.Linq; using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.Routing; namespace LaDOSE.Api.Helpers { /// /// The controllers in this project are attribute-routed but do not carry [ApiController]. /// Without it MVC never sets ApiExplorer visibility, so ApiExplorer yields no descriptions /// and the generated OpenAPI document comes out with an empty "paths" object. /// This convention opts the attribute-routed actions into ApiExplorer for the /// OpenAPI/Scalar tooling only, without pulling in the [ApiController] behaviours /// (automatic 400 responses, [FromBody] inference) that would change runtime binding. /// public class ApiExplorerVisibilityConvention : IControllerModelConvention { public void Apply(ControllerModel controller) { // Default the controller to hidden, then opt in action by action. controller.ApiExplorer.IsVisible ??= false; foreach (var action in controller.Actions) { if (action.ApiExplorer.IsVisible != null) { continue; } // An action with a [Route] but no verb attribute (e.g. BotEventController's // CreateBotEvent) matches every HTTP method, so ApiExplorer reports an empty // method and OpenAPI generation throws "Unsupported HTTP method". // Only document actions that pin down a verb. action.ApiExplorer.IsVisible = action.Attributes .OfType() .Any(provider => provider.HttpMethods?.Any() == true); } } } } #endif