42 lines
1.7 KiB
C#
42 lines
1.7 KiB
C#
#if DEBUG
|
|
using System.Linq;
|
|
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
|
using Microsoft.AspNetCore.Mvc.Routing;
|
|
|
|
namespace LaDOSE.Api.Helpers
|
|
{
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
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<IActionHttpMethodProvider>()
|
|
.Any(provider => provider.HttpMethods?.Any() == true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|