dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.19k stars 9.93k forks source link

ExcludeFromDescriptionAttribute not excluding controller actions from OpenAPI document #57425

Open davidkarlsson opened 3 weeks ago

davidkarlsson commented 3 weeks ago

Is there an existing issue for this?

Describe the bug

I started a discussion about this in https://github.com/dotnet/aspnetcore/discussions/57422 but I will summarize it again here.

Using Microsoft.AspNetCore.OpenApi with .NET 9 preview 7 you can't exclude controller actions from the OpenAPI document by using ExcludeFromDescriptionAttribute on the controller or the action of a controller. You can however exclude them by using ApiExplorerSettingsAttribute and setting its IgnoreApi property to true.

Is this the intended behaviour of ExcludeFromDescription? In the OpenAPI documentation about this it says that ExcludeFromDescriptionAttribute is for minimal APIs but in the discussion about this it was pointed out that this might be a bug and that the attribute should work with controllers as well?

Also, if this isn't a bug and ApiExplorerSettingsAttribute should instead be used for excluding controller actions from the OpenAPI document shouldn't that at least be documented together with the ExcludeFromDescription documentation in the Work with OpenAPI documents doc?

Expected Behavior

I expected ExcludeFromDescriptionAttribute to exclude a controller action from the OpenAPI document when added to either the action's controller or to the action directly.

And if this attribute isn't suppose to be used with controllers I expected the documentation about excluding endpoints to say so and instead suggest using ApiExplorerSettingsAttribute for it.

Steps To Reproduce

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi();

builder.Services.AddControllersWithViews();

var app = builder.Build();

app.UseRouting();

app.UseAuthorization();

app.MapOpenApi();

app.Run();

[ApiController]
[Route("Api/[action]")]
public class PublicApiController : ControllerBase
{
    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public IActionResult Public()
    {
        return Ok();
    }
}

[ApiController]
[Route("Api/[action]")]
[ExcludeFromDescription]
//[ApiExplorerSettings(IgnoreApi = true)]
public class InternalApiController : ControllerBase
{
    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public IActionResult Internal()
    {
        return Ok();
    }
}

/openapi/v1.json:

{
  "openapi": "3.0.1",
  "info": {
    "title": "OpenApiTest | v1",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://localhost:5001"
    }
  ],
  "paths": {
    "/Api/Internal": {
      "get": {
        "tags": [
          "InternalApi"
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/Api/Public": {
      "get": {
        "tags": [
          "PublicApi"
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": { },
  "tags": [
    {
      "name": "InternalApi"
    },
    {
      "name": "PublicApi"
    }
  ]
}

Exceptions (if any)

No response

.NET Version

9.0.100-preview.7.24407.12

Anything else?

No response

captainsafia commented 3 weeks ago

Is this the intended behaviour of ExcludeFromDescription? In the OpenAPI documentation about this it says that ExcludeFromDescriptionAttribute is for minimal APIs but in the discussion about this it was pointed out that this might be a bug and that the attribute should work with controllers as well?

Yes, this is the intended behavior of ExcludeFromDescriptionAttribute. Under the hood, the IExcludeFromDescription metadata that this attribute implements is only respected by the IApiDescriptionProvider implementation (ref).

Backport minimal API-specific attributes/metadata to controller-based APIs isn't a big priority these days so that distinction will likely stay.

That being said, with regard to...

Also, if this isn't a bug and ApiExplorerSettingsAttribute should instead be used for excluding controller actions from the OpenAPI document shouldn't that at least be documented together with the ExcludeFromDescription documentation in the Work with OpenAPI documents doc?

We're hoping to do a refactor of the docs to be a bit better about comparing/contrasting how things can be done for minimal vs. controller-based APIs so that these kinds of differences will be easier to discover in the future. The refactor will take a while to do though so the intermediary state is a little unfortunate.