Swagger版本控制不起作用,它显示所有端点,而不考虑所选的API版本

ni65a41a  于 2023-05-28  发布在  其他
关注(0)|答案(3)|浏览(111)

全部!
我在ASP.NET Core 3.1应用程序中使用Swagger。
我需要为新版本的API创建一个端点,并使用与以前版本相同的路由。
我的控制器是:

namespace Application.Controllers
{
    [ApiVersion("1")]
    [ApiVersion("2")]
    [ApiController]
    [Route("api/v{version:apiVersion}")]
    public class CustomController: ControllerBase
    {
        [HttpGet]
        [Route("result")]
        public IActionResult GetResult()
        {
            return Ok("v1")
        }

        [HttpGet]
        [MapToApiVersion("2")]
        [Route("result")]
        public IActionResult GetResult(int number)
        {
            return Ok("v2")
        }
    }
}

我的配置:

services.AddApiVersioning(
                options =>
                {
                    options.ReportApiVersions = true;
                });

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc($"v1", new OpenApiInfo { Title = "api1", Version = $"v1" });

                c.SwaggerDoc($"v2", new OpenApiInfo { Title = "api2", Version = $"v2" });         
         

                c.OperationFilter<RemoveVersionParameterFilter>();
                c.DocumentFilter<ReplaceVersionWithExactValueInPathFilter>();
                c.EnableAnnotations();
            });
app.UseSwagger().UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint($"/swagger/v1/swagger.json", $"api1 v1");
                c.SwaggerEndpoint($"/swagger/v2/swagger.json", $"api2 v2");
            });

加载后,我得到一个错误:Fetch error undefined /swagger/v1/swagger.json但是如果我将第二个路由更改为“resutlTwo”,我可以在swagger中观察到两个端点,忽略当前版本(api 1 v1或api 2 v2)
如何才能在每个API版本中只看到1个端点?

vwkv1x7d

vwkv1x7d1#

感谢Roar S.的帮助!
我刚加了

services.AddApiVersioning(apiVersioningOptions =>
            {
                apiVersioningOptions.ReportApiVersions = true;
                apiVersioningOptions.ApiVersionReader = new UrlSegmentApiVersionReader();
            });

c.DocInclusionPredicate((version, desc) =>
                {
                    var endpointMetadata = desc.ActionDescriptor.EndpointMetadata;

                    if (!desc.TryGetMethodInfo(out MethodInfo methodInfo))
                    {
                        return false;
                    }

                    var specificVersion = endpointMetadata
                            .Where(data => data is MapToApiVersionAttribute)
                            .SelectMany(data => (data as MapToApiVersionAttribute).Versions)
                            .Select(apiVersion => apiVersion.ToString())
                            .SingleOrDefault();

                    if (!string.IsNullOrEmpty(specificVersion))
                    {
                        return $"v{specificVersion}" == version;
                    }

                    var versions = endpointMetadata
                            .Where(data => data is ApiVersionAttribute)
                            .SelectMany(data => (data as ApiVersionAttribute).Versions)
                            .Select(apiVersion => apiVersion.ToString());

                    return versions.Any(v => $"v{v}" == version);
                });

它将端点拆分到不同的文件。

jbose2ul

jbose2ul2#

我刚刚用这个设置测试了你的情况。你缺少UrlSegmentApiVersionReader

public class SwaggerOptions
{
    public string Title { get; set; }
    public string JsonRoute { get; set; }
    public string Description { get; set; }
    public List<Version> Versions { get; set; }

    public class Version
    {
        public string Name { get; set; }
        public string UiEndpoint { get; set; }
    }
}

在启动#ConfigureServices

// Configure versions 
        services.AddApiVersioning(apiVersioningOptions =>
        {
            apiVersioningOptions.ReportApiVersions = true;
            apiVersioningOptions.ApiVersionReader = new UrlSegmentApiVersionReader();
        });

        // Register the Swagger generator, defining 1 or more Swagger documents
        services.AddSwaggerGen(swaggerGenOptions =>
        {
            var swaggerOptions = new SwaggerOptions();
            Configuration.GetSection("Swagger").Bind(swaggerOptions);

            foreach (var currentVersion in swaggerOptions.Versions)
            {
                swaggerGenOptions.SwaggerDoc(currentVersion.Name, new OpenApiInfo
                {
                    Title = swaggerOptions.Title,
                    Version = currentVersion.Name,
                    Description = swaggerOptions.Description
                });
            }

            swaggerGenOptions.DocInclusionPredicate((version, desc) =>
            {
                if (!desc.TryGetMethodInfo(out MethodInfo methodInfo))
                {
                    return false;
                }
                var versions = methodInfo.DeclaringType.GetConstructors()
                    .SelectMany(constructorInfo => constructorInfo.DeclaringType.CustomAttributes
                        .Where(attributeData => attributeData.AttributeType == typeof(ApiVersionAttribute))
                        .SelectMany(attributeData => attributeData.ConstructorArguments
                            .Select(attributeTypedArgument => attributeTypedArgument.Value)));

                return versions.Any(v => $"{v}" == version);
            });

            swaggerGenOptions.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"));
            
            ... some filter settings here 
        });

在启动#配置

var swaggerOptions = new SwaggerOptions();
Configuration.GetSection("Swagger").Bind(swaggerOptions);
app.UseSwagger(option => option.RouteTemplate = swaggerOptions.JsonRoute);

app.UseSwaggerUI(option =>
{
  foreach (var currentVersion in swaggerOptions.Versions)
  {
    option.SwaggerEndpoint(currentVersion.UiEndpoint, $"{swaggerOptions.Title} {currentVersion.Name}");
  }
});

appsettings.json

{
  "Swagger": {
    "Title": "App title",
    "JsonRoute": "swagger/{documentName}/swagger.json",
    "Description": "Some text",
    "Versions": [
      {
        "Name": "2.0",
          "UiEndpoint": "/swagger/2.0/swagger.json"
      },
      {
        "Name": "1.0",
        "UiEndpoint": "/swagger/1.0/swagger.json"
      }
    ]
  }
}

这段代码与我在SO上处理的一个相关问题非常相似。

j2qf4p5b

j2qf4p5b3#

谢谢你们,这个代码样本对我帮助很大。您可以将其用于1.0和2.0等版本。这对我很有效

c.DocInclusionPredicate((version, desc) =>
            {
                IList<object> endpointMetadata = desc.ActionDescriptor.EndpointMetadata;

                if (!desc.TryGetMethodInfo(out MethodInfo methodInfo))
                {
                    return false;
                }

                string specificVersion = endpointMetadata
                    .Where(data => data is MapToApiVersionAttribute)
                    .SelectMany(data => (data as MapToApiVersionAttribute).Versions)
                    .Select(apiVersion => apiVersion.ToString())
                    .SingleOrDefault();

                if (!string.IsNullOrEmpty(specificVersion))
                {
                    return $"v{specificVersion}" == version;
                }

                List<string> versions = endpointMetadata
                    .OfType<ApiVersionAttribute>()
                    .SelectMany(data => data.Versions)
                    .Select(apiVersion => apiVersion.ToString())
                    .Select(v =>
                    {
                        var versionParts = v.Split('.');
                        return versionParts.Length > 0 ? versionParts[0] : v;
                    })
                    .ToList();

                return versions.Any(v => $"v{v}" == version);
            });

谢谢你的帮助<3

相关问题