question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Swagger paths include http method names

See original GitHub issue

I’m not sure if this is a bug in Versioning, in Swagger, or in my routes.

I’m using ASP.NET WebApi and Versioning version 4.1.1.

My controller looks like this (I’ve cut it down to what’s relevant):

namespace MyProj.Api.v1.Controllers
{
    public class BookingsController : BaseApiController
    {
        /// <summary>
        /// Get unavailable information about bookings or blocks.
        /// </summary>
        public IPageableEnumerable<BookingModel> Get(int[] arg1, DateTime? arg2, ...) { ... }

        /// <summary>
        /// Get unavailable information about a specific booking or blocked-off time.
        /// </summary>
        public BookingModel Get(int id, bool? someOtherArgs, ...) { ... }

        /// <summary>
        /// Gets a list of booking availability information entries based on criteria.
        /// </summary>
        [HttpGet]
        public AvailabilityViewModel Availability(int[] arg1, DateTime? arg2, ...) { ... }
    }
}

I would expect Swagger to report paths of

  • /v1/bookings (Description: Get unavailable information about bookings or blocks.)
  • /v1/bookings/{id} (Description: Get unavailable information about a specific booking or blocked-off time.)
  • /v1/bookings/availability (Description: Gets a list of booking availability information entries based on criteria.)

But instead it outputs this: image

Two problems here:

  1. The first path is getting its description from the Availability endpoint.
  2. The /v1/bookings/get path should not include the /get at the end.

Here is my configuration setup:

config.Routes.MapHttpRoute(name: "Api", routeTemplate: "v{apiVersion}/{controller}/{id}",
    defaults: null,
    constraints: new { apiVersion = new ApiVersionRouteConstraint(), id = new RegexOptionalConstraint(@"^(\d+)$") });

config.Routes.MapHttpRoute(name: "ApiAction", routeTemplate: "v{apiVersion}/{controller}/{action}",
    defaults: new { id = (int?)null, action = RouteParameter.Optional },
    constraints: new { apiVersion = new ApiVersionRouteConstraint(), action = new RegexOptionalConstraint(@"^([a-zA-Z]+)$") });

config.AddApiVersioning(options =>
{
    //https://github.com/microsoft/aspnet-api-versioning/wiki/API-Version-Conventions#version-by-namespace-convention
    options.Conventions.Add(new VersionByNamespaceConvention()); 
    options.ReportApiVersions = true;
});

var apiExplorer = config.AddVersionedApiExplorer(options =>
{
    // format the version as "'v'major[.minor][-status]"
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl = true;
    options.SubstitutionFormat = "VVV";
});

var swaggerConfig = config.EnableSwagger(
    "swagger/{apiVersion}",
    swagger =>
    {
        swagger.MultipleApiVersions(
            (apiDescription, version) => apiDescription.GetGroupName() == version,
            info =>
            {
                foreach (var group in apiExplorer.ApiDescriptions)
                {
                    var builder = info.Version(group.Name, $"MyProj API {group.ApiVersion}");

                    if (group.IsDeprecated)
                    {
                        builder.Description("This API version has been deprecated.");
                    }
                }
            });

        // add a custom operation filter which sets default values
        swagger.OperationFilter<SwaggerDefaultValues>();

        // add a documnet filter to format the routes accurately
        swagger.DocumentFilter<SwaggerLowercasePaths>();

        // integrate xml comments
        swagger.IncludeXmlComments(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin/MyProj.Api.xml"));

        swagger.UseFullTypeNameInSchemaIds();

        // Without this, I get a "Multiple operations with path 'v1/Bookings/{id}' and method 'GET'" swagger error
        swagger.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:8

github_iconTop GitHub Comments

1reaction
ithielnorcommented, Jun 17, 2022

I gave up and switched to Attribute routing. Couldn’t get around it otherwise.

0reactions
commonsensesoftwarecommented, Aug 24, 2022

Looks like there is a solution to this issue.

6.0 has been officially released and contains all of the fixes, including the LockRecursionException problem. The 6.0 release may be a bit of an initial disruption as many things have changed. The 5.1 also contains the fix and will be simple to update, but I’m still fighting getting NuGet to accept my signing certificate for the old packages. I’m sure it will be solved - eventually. If you’d like to update now, switching to 6.0 is the way to go. Ultimately, that will the long-term direction anyway.

Thanks again for the repro. Glad you are unblocked.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Paths and Operations
For each path, you define operations (HTTP methods) that can be used to access that path. OpenAPI 3.0 supports get , post ,...
Read more >
Swagger UI not showing operations with same Path but ...
In the Swagger documentation it states: "Swagger defines a unique operation as a combination of a path and an HTTP method." This would...
Read more >
Using OpenAPI and Swagger UI
Apply a sort to the operation list of each API. It can be 'alpha' (sort by paths alphanumerically), 'method' (sort by HTTP method)...
Read more >
How to put multiple methods/functions having same path ...
I tried to put multiple methods having same path value (e.g /api-comment) under same tag, but swagger 2.0 failed to display these methods....
Read more >
Get started with Swashbuckle and ASP.NET Core
Swashbuckle.AspNetCore.SwaggerGen: a Swagger generator that builds SwaggerDocument objects directly from your routes, controllers, and models.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found