Dotnet, Swagger does not show version "1.0" info correct

48 views Asked by At

I have a c# project where version "1.0", "1.1", and "1.2-rc1" are defined. The api works for all versions of the api, but swagger does not display the information for version "1.0", it only displays "No operations defined in spec!", swagger does display the correct info for version "1.1" and "1.2-rc1". Can someone see what I am doing wrong when setting up swagger info?

Curl test: Curl test

V1.0 swagger info: V1.0 swagger info

V1.1 swagger info: V1.1 swagger info

Program.cs

using Asp.Versioning;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI;

namespace TestSwagger
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            builder.Services.AddControllers();
            builder.Services.AddEndpointsApiExplorer();

            builder.Services.AddApiVersioning(options =>
            {
                options.AssumeDefaultVersionWhenUnspecified = false;
                options.ReportApiVersions = true;
                options.ApiVersionReader = ApiVersionReader.Combine(new UrlSegmentApiVersionReader());
            })
            .AddApiExplorer(options =>
            {
                // Add the versioned API explorer, which also adds IApiVersionDescriptionProvider service
                // note: the specified format code will format the version as "'v'major[.minor][-status]"
                options.GroupNameFormat = "'v'VVV";
                options.SubstituteApiVersionInUrl = true;
            });

            builder.Services.AddSwaggerGen(action =>
                DefinedApiVersion.GetAllApiVersionValues().ForEach(value =>
                    SetSwaggerDocInfo(action, value)
                )
            );

            builder.Services.AddControllers();

            var app = builder.Build();

            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI(action =>
                {
                    DefinedApiVersion.GetAllApiVersionValues().ForEach(value => AddSwaggerEndpoint(action, value));
                    action.DisplayRequestDuration();
                });
            }

            app.UseHttpsRedirection();

            app.UseAuthorization();

            app.MapControllers();

            app.Run();
        }

        private static void AddSwaggerEndpoint(SwaggerUIOptions action, string apiVersionStr)
        {
            string apiVersionStrWithV = "v" + apiVersionStr;
            action.SwaggerEndpoint($"/swagger/{apiVersionStrWithV}/swagger.json", $"A small test API {apiVersionStrWithV}");
        }

        private static void SetSwaggerDocInfo(SwaggerGenOptions options, string apiVersionStr)
        {
            string apiVersionStrWithV = "v" + apiVersionStr;
            options.SwaggerDoc(apiVersionStrWithV, new OpenApiInfo
            {
                Version = apiVersionStrWithV,
                Title = $"A Test API {apiVersionStrWithV}",
                Description = "An dotnet core web api test ",
                TermsOfService = new Uri("https://localhost/terms"),
                Contact = new OpenApiContact { Name = "Contact", Url = new Uri("http://localhost/contact") },
                License = new OpenApiLicense { Name = "License", Url = new Uri("http://localhost/license") }
            });
        }

    }
}

TestController.cs:

using Asp.Versioning;
using Microsoft.AspNetCore.Mvc;

namespace TestSwagger.Controllers
{
    [ApiVersion(DefinedApiVersion.V1_0)]
    [ApiVersion(DefinedApiVersion.V1_1)]
    [ApiVersion(DefinedApiVersion.V1_2)]
    [ApiController]
    [Route("api/v{version:apiVersion}/[controller]")]
    public class TestController : ControllerBase
    {
        [MapToApiVersion(DefinedApiVersion.V1_0)]
        [MapToApiVersion(DefinedApiVersion.V1_1)]
        [MapToApiVersion(DefinedApiVersion.V1_2)]
        [HttpGet("Method1")]
        public string Method1()
        {
            return "1";
        }
        [MapToApiVersion(DefinedApiVersion.V1_1)]
        [MapToApiVersion(DefinedApiVersion.V1_2)]
        [HttpGet("Method2")]
        public string Method2()
        {
            return "2";
        }
        [MapToApiVersion(DefinedApiVersion.V1_2)]
        [HttpGet("Method3")]
        public string Method3()
        {
            return "3";
        }
    }
}

DefinedApiVersions.cs:

using System.Reflection;

namespace TestSwagger
{

    public static class DefinedApiVersion
    {
        public const string V1_0 = "1.0";
        public const string V1_1 = "1.1";
        public const string V1_2 = "1.2-rc1";

        public static List<string> GetAllApiVersionValues()
        {
            return typeof(DefinedApiVersion)
           .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
           .Where(x => x.IsLiteral && x.FieldType == typeof(string))
           .Select(x => x.GetRawConstantValue()?.ToString() ?? string.Empty)
           .ToList();
        }
    }
}
1

There are 1 answers

0
Jonathan Feenstra On

Since the options.GroupNameFormat is set to "VVV" (major, optional minor version, and status), your version "1.0" is formatted as "1". As you mentioned in your comment, you can change the V1_0 string to "1" to make the Swagger data display, or you can change the version format to "VVVV" (major, minor version, and status) to keep using "1.0".