Skip to content

OpenApi ApiVersionAttribute.Deprecated not reflected in schema #57853

Open
@JTeeuwissen

Description

@JTeeuwissen

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When adding an ApiVersionAttribute with Deprecated = true to a controller, the operation schema is not marked as "deprecated": true

Expected Behavior

When adding an ApiVersionAttribute with Deprecated = true to a controller, the operation schema should be marked with "deprecated": true

Steps To Reproduce

Services

services.AddRouting();
services.AddControllers();

services.AddApiVersioning();
services.AddVersionedApiExplorer(options =>
{
  options.GroupNameFormat = "'v'VVV";
  options.SubstituteApiVersionInUrl = true;
});
services.AddOpenApi("v1");

Controller

[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1", Deprecated = true)]
public class ExampleController : ControllerBase
{
  [HttpGet("{id}")]
  public int Get(int id)
  {
    return id;
  }
}

Result

{
  "openapi": "3.0.1",
  "info": {
    "title": "ExampleProject | v1",
    "version": "1.0.0"
  },
  "paths": {
    "/api/v1/Example/{id}": {
      "get": {
        "tags": [
          "Example"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "integer",
                  "format": "int32"
                }
              },
              "application/json": {
                "schema": {
                  "type": "integer",
                  "format": "int32"
                }
              },
              "text/json": {
                "schema": {
                  "type": "integer",
                  "format": "int32"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": { },
  "tags": [
    {
      "name": "Example"
    }
  ]
}

Exceptions (if any)

No response

.NET Version

9.0.100-rc.1.24452.12

Anything else?

An IOpenApiOperationTransformer like below could serve as a workaround, but I would prefer this functionality to be built in.

class ApiVersionDeprecatedTransformer : IOpenApiOperationTransformer
{
  public Task TransformAsync(
    OpenApiOperation operation,
    OpenApiOperationTransformerContext context,
    CancellationToken cancellationToken)
  {
    if (context.Description.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor &&
        context.Description.Properties.TryGetValue(typeof(ApiVersion), out var apiVersionObject) &&
        apiVersionObject is ApiVersion apiVersion)
    {
      var versionAttributes = controllerActionDescriptor.ControllerTypeInfo.GetCustomAttributes<ApiVersionAttribute>();
      if (versionAttributes.Any(attribute => attribute.Deprecated && attribute.Versions.Single() == apiVersion))
      {
        operation.Deprecated = true;
      }
    }

    return Task.CompletedTask;
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcarea-mvcIncludes: MVC, Actions and Controllers, Localization, CORS, most templatesfeature-openapi

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions