swagger 如何使用aspnet ApiVersioning在Swashbuckle中配置MultipleApiVersions

unftdfkk  于 2022-12-13  发布在  其他
关注(0)|答案(3)|浏览(183)

如何配置swashbuckle以与Aspnet API版本化一起使用?https://github.com/Microsoft/aspnet-api-versioning
在我的Startup.cs中,我有以下代码来初始化基于属性的路由、API版本控制和swagger。

var constraintResolver = new DefaultInlineConstraintResolver()
{
    ConstraintMap =
    {
        ["apiVersion"] = typeof( ApiVersionRouteConstraint )
    }
};
config.MapHttpAttributeRoutes(constraintResolver);
config.AddApiVersioning();

config.EnableSwagger(c =>
{
    c.MultipleApiVersions(
        (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
        (vc) =>
        {
            vc.Version("v1", "Swashbuckle Dummy API V1");
            vc.Version("v2", "Swashbuckle Dummy API V2");
        });
}


public static bool ResolveVersionSupportByRouteConstraint(ApiDescription apiDesc, string targetApiVersion)
{
    var versionConstraint = (apiDesc.Route.Constraints.ContainsKey("apiVersion"))
        ? apiDesc.Route.Constraints["apiVersion"] as RegexRouteConstraint
        : null;

    return (versionConstraint == null)
        ? false
        : versionConstraint.Pattern.Split('|').Contains(targetApiVersion);
}

当ResolveVersionSupportByRouteConstraint方法触发路由模板时,该模板包含文字API字符串“api/v{version}/users”我的用户控制器用[ApiVersion(“1.0”)]装饰,并且我定义了以下路由[Route(“api/v{version:apiVersion}/users”)]。当我用postman点击api/v1/users时,调用工作,但我不知道如何用Swashbuckle/Swagger使其工作。
我希望我的swagger文档看起来像asp.net核心API样板文件的示例,只是我使用的是Owin和owin启动类,而不是.net核心:https://github.com/ASP-NET-Core-Boilerplate/Templates/blob/master/MVC%206%20API.md

aamkag61

aamkag611#

你可以找到例子here这是我如何在启动自托管owin应用程序:

public void Configuration(IAppBuilder appBuilder)
    {
        HttpConfiguration config = new HttpConfiguration();
        //configure your app

        config.AddApiVersioning(o =>
        {
            o.ReportApiVersions = true;
            o.ApiVersionReader = new UrlSegmentApiVersionReader();
        });
        var constraintResolver = new DefaultInlineConstraintResolver()
        {
            ConstraintMap = { ["apiVersion"] = typeof(ApiVersionRouteConstraint) }
        };
        config.MapHttpAttributeRoutes(constraintResolver);
        SwaggerConfiguration.Configure(config);            
        appBuilder.UseWebApi(config);
    }

swagger的配置非常简单,主要部分在这里VersionedApiExplorer(确保,你传递了正确的groupnameformat你的api,我的格式是v1,v2等):

public static class SwaggerConfiguration
{       
    public static void Configure(HttpConfiguration config)
    {
        var apiExplorer = config.AddVersionedApiExplorer(o => o.GroupNameFormat = "'v'V");
        config.EnableSwagger(
                swagger =>
                {
                    swagger.MultipleApiVersions(
                        (apiDesc, targetApiVersion) => apiDesc.GetGroupName() == targetApiVersion,
                        versionBuilder =>
                        {
                            foreach (var group in apiExplorer.ApiDescriptions)
                            {
                                var description = "";
                                if (group.IsDeprecated) description += "This API deprecated";

                                versionBuilder.Version(group.Name, $"Service API {group.ApiVersion}")
                                    .Description(description);
                            }
                        });
                    swagger.DocumentFilter<VersionFilter>();
                    swagger.OperationFilter<VersionOperationFilter>();
                })
            .EnableSwaggerUi(cfg => cfg.EnableDiscoveryUrlSelector());
    }

在控制器中添加属性ApiVersion和RoutePrefix

[ApiVersion("1")]
[RoutePrefix("api/v{version:apiVersion}/history")]
public class HistoryController: ApiController

如果您对VersionFilter和VersionOperationFilter感到困惑,可以使用相应的代码。此筛选器会修改结果路由和参数(如果不这样,您的路由将看起来像/v{version}/{actionName},并包含所需的参数版本)

public class VersionFilter : IDocumentFilter
{
    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
    {
        swaggerDoc.paths = swaggerDoc.paths
            .ToDictionary(
                path => path.Key.Replace("v{version}", swaggerDoc.info.version),
                path => path.Value
            );
    }
}
public class VersionOperationFilter : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        var version = operation.parameters?.FirstOrDefault(p => p.name == "version");
        if (version != null)
        {
            operation.parameters.Remove(version);
        }
    }
}
eimct9ow

eimct9ow2#

我认为ResolveVersionSupportByRouteConstraint方法可能是错误的,参见:https://github.com/domaindrivendev/Swashbuckle/issues/197#issuecomment-75288894

x4shl7ld

x4shl7ld3#

请注意,您可以通过适当配置ApiExplorer来实现版本替换。
请参阅代码片段:

var apiExplorer = config.AddVersionedApiExplorer(config =>
{
    config.SubstituteApiVersionInUrl = true;

这将替换路径中版本,并从操作参数中删除版本参数

相关问题