Rory McCrossan
Rory McCrossan

Reputation: 337560

How can I supply a path parameter to the displayed path in SwaggerUi?

I have setup Swagger/Swashbuckle on my WebAPI project. I have followed the guide from Microsoft which covers how to setup Aspnet.WebApi.Versioning with Swagger. My API has multiple versions, so there is a {version} parameter set in the route attributes, like this:

[ApiVersion("2")]
[RoutePrefix("api/{version:apiVersion}/values")]
public class AccountController : ApiController
{
    [Route("UserInfo")]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

My issue is that this shows a {version} attribute in the path shown in the docs, like this:

enter image description here

Instead I want this path attribute to actually have the value in the ApiVersion attribute, so that there can be no confusion for the clients who read the documentation. Ideally, given that the UrlDiscoverySelector is set to v2 the paths above should be:

/api/2/account/userinfo
/api/2/account/externallogin
/api/2/account/manageinfo

My attempts to simply replace the {version} in the RelativePath of the ApiExplorer worked in the UI, but broke the test functionality as {version} was changed to a query parameter instead of a path, which is not how my API is configured.

Is it possible I can amend the values in the ApiExplorer before swagger builds the documentation while still retaining test functionality?

Upvotes: 1

Views: 3667

Answers (2)

Chris Martinez
Chris Martinez

Reputation: 4368

The API Explorer for API versioning now supports the behavior out-of-the-box using:

options.SubstituteApiVersionInUrl = true

This will do the substitution work for you and removes the API version parameter from the action descriptor. You generally don't need to change the default format applied to the substituted value, but you can change it using:

options.SubstitutionFormat = "VVV"; // this is the default

Upvotes: 3

Kirill.S
Kirill.S

Reputation: 1

I'm using a Swashbuckle and used a Document filter

public class VersionedOperationsFilter : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
    {
        foreach (var apiDescriptionsGroup in context.ApiDescriptionsGroups.Items)
        {
            var version = apiDescriptionsGroup.GroupName;
            foreach (ApiDescription apiDescription in apiDescriptionsGroup.Items)
            {
                apiDescription.RelativePath = apiDescription.RelativePath.Replace("{version}", version);
            }
        }
    }
}

and in ConfigureServices method in Startup.cs add this filter:

services.AddMvc();
        var defaultApiVer = new ApiVersion(1, 0);


        services.AddApiVersioning(option =>
        {
            option.ReportApiVersions = true;
            option.AssumeDefaultVersionWhenUnspecified = true;
            option.DefaultApiVersion = defaultApiVer;
        });

        services.AddMvcCore().AddVersionedApiExplorer(e=>e.DefaultApiVersion = defaultApiVer);

        services.AddSwaggerGen(
            options =>
            {
                var provider = services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();
                options.DocumentFilter<VersionedOperationsFilter>();

                //// add a swagger document for each discovered API version
                //// note: you might choose to skip or document deprecated API versions differently
                foreach (var description in provider.ApiVersionDescriptions)
                {
                        options.SwaggerDoc(description.GroupName.ToString(),
                            CreateInfoForApiVersion(description));
                }

                //// integrate xml comments
                options.IncludeXmlComments(Path.ChangeExtension(Assembly.GetEntryAssembly().Location, "xml"));

            });

end result in Swagger UI

Upvotes: 0

Related Questions