Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ActionDescriptor no longer returns an ApiVersionModel property #1026

Closed
1 task done
karun-verghese opened this issue Oct 4, 2023 · 2 comments
Closed
1 task done

Comments

@karun-verghese
Copy link

karun-verghese commented Oct 4, 2023

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Hi all,

We recently migrated from Microsoft.AspNetCore.Mvc.Versioning (5.1.0) to the new Asp.Versioning.Mvc (7.0.1) package. I noticed that some of the Swashbuckle.AspNetCore integrations stopped working. I have only changed the Asp.Versioning package, not the Swashbuckle package.

My startup looks something like this:

        services.AddApiVersioning(options =>
        {
               options.AssumeDefaultVersionWhenUnspecified = true;
               options.ApiVersionReader = new QueryStringApiVersionReader("version");
               options.DefaultApiVersion = new ApiVersion(1, 0); 
        }).AddMvc().AddApiExplorer();

       //Swashbuckle integration
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo
            {
                Title = "API V1",
                Version = "v1",
            });
            c.SwaggerDoc("v2", new OpenApiInfo
            {
                Title = "API V2",
                Version = "v2",
            });
            c.DocInclusionPredicate((docName, apiDesc) =>
            {
                // The API version model is now being returned as null which seems to be a change in behaviour
                var actionApiVersionModel = apiDesc.ActionDescriptor?.GetApiVersion();
                if (actionApiVersionModel == null)
                {
                    return false;
                }
                return actionApiVersionModel.DeclaredApiVersions.Any(v => docName.Contains($"v{v}", StringComparison.InvariantCultureIgnoreCase));
            });
            c.EnableAnnotations();
            c.OperationFilter<ApiOperationFilter>();
            var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
            var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
            c.IncludeXmlComments(xmlPath);
        });

The custom extension method for the ActionDescriptor looks like this:

   public static class ActionDescriptorExtensions
    {
        public static ApiVersionModel GetApiVersion(this ActionDescriptor actionDescriptor)
        {
                   return actionDescriptor?.Properties
                      .Where((kvp) => ((Type)kvp.Key).Equals(typeof(ApiVersionModel)))
                      .Select(kvp => kvp.Value as ApiVersionModel).FirstOrDefault();
        }
    }

The earlier behaviour was such that the ActionDescriptor used to contain a property of type "ApiVersionModel" in the Dictionary "Properties". This no longer seems to be the case. As a result the logic in the DocInclusionPredicate doesn't work and the OpenAPI spec doesn't contain any API operations.

The API version model is something we heavily rely on in our custom ApiOperationFilter to customize our Open API documents. So question is, is this no longer supported? Or am I missing some option/configuration somewhere that enables this? If it's not, is there some alternative way I can get the ApiVersionModel for each operation?

Expected Behavior

What I expect is the ActionDescriptor to continue to support the ApiVersionModel which gives useful information on DeclaredApiVersions, DeprecatedApiVersions etc.

Steps To Reproduce

No response

Exceptions (if any)

No response

.NET Version

7.0.400

Anything else?

.Net Core Version 7.0.10

@commonsensesoftware
Copy link
Collaborator

Things changed a little as was called out in #808 under API Version Model Extensions. I'm observing that a lot of people are not finding this during their migrations so I work on lifting some of that information out into a more formal migration guide.

The old API to new API mapping is:

  • GetApiVersionModel(ApiVersionMapping)GetApiVersionMetadata()
  • GetApiVersionModel()ApiVersionMetadata.Map(ApiVersionMapping.Explicit)
  • MappingTo(ApiVersion)ApiVersionMetadata.MappingTo(ApiVersion)
  • IsMappedTo(ApiVersion)ApiVersionMetadata.IsMappedTo(ApiVersion)

This enables the API to be common for the older ASP.NET Web API stack as well as the ASP.NET Core stack. Action descriptor properties are no longer used so that API Versioning can work for Minimal APIs, which doesn't support them.

GetApiVersionMetadata() is generally the thing you are looking for and you shouldn't have to build your own extension methods to get the properties out. You can obviously create more refined extension methods, but they can build upon what is provided. If you really want to dive down into what these extension methods do, have a look at:

public static ApiVersionMetadata GetApiVersionMetadata( this ActionDescriptor action )

or

var metatadata = apiDescription.ActionDescriptor.GetApiVersionMetadata();

I hope that helps.

@karun-verghese
Copy link
Author

Thanks a lot! I'll check this out. Yes some documentation on this in the wiki would definitely help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants