Skip to content

remove -status in AddVersionedApiExplorer not work #983

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

Closed
1 task done
ebrahimkhodadadi opened this issue Apr 10, 2023 · 3 comments
Closed
1 task done

remove -status in AddVersionedApiExplorer not work #983

ebrahimkhodadadi opened this issue Apr 10, 2023 · 3 comments

Comments

@ebrahimkhodadadi
Copy link

ebrahimkhodadadi commented Apr 10, 2023

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

i use [ApiVersion("1.0-Public")] attribute
for split definitions in Swagger after that for routing just added

.AddVersionedApiExplorer(opt =>
                {
                    opt.GroupNameFormat = "'v'VVV";
                    opt.SubstitutionFormat = "V";
                    opt.SubstituteApiVersionInUrl = true;
                });

to set the major version
[Route("v{version:apiVersion}/[controller]/[action]")]
this sample works fine

var apiVersion = new ApiVersion( 1, 0 , "Public");
Console.WriteLine( apiVersion.ToString( "V" ) );

but in asp.net core APIs formatting of the version doesn't work

Expected Behavior

No response

Steps To Reproduce

No response

Exceptions (if any)

No response

.NET Version

5.0.0

Anything else?

No response

@commonsensesoftware
Copy link
Collaborator

Can you quantify what you mean by it doesn't work? What happens? What do you expect to happen?

As shown, this is what will happen:

var apiVersion = new ApiVersion( 1, 0 , "Public");
Console.WriteLine( apiVersion.ToString( "V" ) );

Output:

1

The full formatting options are documented in the wiki under the version format topic.

The status is fundamentally part of the API version when you use it. It is possible to format parts of an API version for display purposes, but you cannot abuse to formatting create a 🐶 and 🐴 show where the client asks for some API version - say 1.0 and it somehow magically maps to another API version such as 1.0-Public. If your API version is 1.0-Public, then the request must include the full API version (ex: ?api-version=1.0-Public). Partial and implicit matches are not allowed - by design.

You can hide the status when formatting the API version used for grouping purposes. For example, you can show 1.0, when it really maps to 1.0-Public. The only convenience is that the name is shorter. I'm not sure why you'd want to do that. It would be confusing to clients or anyone reading the documentation. They still have to use 1.0-Public in Try It Now! as well as any other request.

@ebrahimkhodadadi
Copy link
Author

ebrahimkhodadadi commented Apr 10, 2023

my purpose is to divide definitions in swagger like this
image
but I do not want any change in my routing I already read
#516
is that logical?

@commonsensesoftware
Copy link
Collaborator

Based on what you are showing, it would appear your goal is to provide an additional level of organization or grouping to a set of APIs. An API version status is not meant for that.

There are multiple ways that you can provide additional grouping, but at the end of the day, the Swagger UI only affords for a single dropdown without some significant customization to the UI. I can't say exactly how, nor can think of someone that has put forth that much effort, but it is technically possible.

ASP.NET Core and the API Explorer explorer do provide a way to define a group, but that typically conflicts with using the API version itself as the group once you add versioning. The desire to have both has come up enough that now there is a built in feature to support it.

Let's assume you have the following controller.

[ApiVersion(1.0)]
[ApiController]
[ApiExplorerSettings(GroupName="Admin")]
[Route("admin/[controller]")]
public class SecretsController : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok();
}

This defines the group Admin which has the API version 1.0. Next you'll need to make the following changes to the configuration setup:

services.AddApiVersioning()
        .AddApiExplorer(options =>
        {
            options.GroupNameFormat = "V";
            options.FormatGroupName = (group, version) => $"API v{version}-{group}";
            options.SubstitutionFormat = "V";
            options.SubstituteApiVersionInUrl = true;
        });

In order for the FormatGroupName callback to be invoked, it must be defined (obviously) and a group name must be specified via IApiDescriptionGroupNameProvider.GroupName, which can be done through ApiExplorerSettingsAttribute. The callback receives the group name and the ApiVersion already formatted as a string according to GroupNameFormat. You are then free to decide how the two values are combined.

If you did this for all of your controllers, that will display in the list as you've shown. The actually API version is still 1.0 so the request URL would be /admin/secret?api-version=1 or whatever method of versioning you've configured.

Also be aware that you've changed the SubstitutionFormat to "V" which will only include the major version number. If you ever have an API version which includes a minor version, the wrong requests will be made from the Swagger UI. The default is "VVV", which will include the major version, minor version if it is not 0, and the status, if there is one. That is probably 99% of the cases. It is configurable in case you want something else like "F" or "VVVV", which will show all of the parts, all of the time, as long as they are present.

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