如何使用 aspnet ApiVersioning 在 Swashbuckle 中配置 MultipleApiVersions
How to configure MultipleApiVersions in Swashbuckle using aspnet ApiVersioning
如何配置 swashbuckle
以使用 Aspnet API
verisoning?
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")]。当我用邮递员打 api/v1/users 时,呼叫有效,但我不知道如何使用 Swashbuckle/Swagger.
我希望我的 swagger 文档看起来像 asp.net 核心 api 样板的示例,除了我在 owin 启动 class 中使用 Owin 而不是 .net 核心: https://github.com/ASP-NET-Core-Boilerplate/Templates/blob/master/MVC%206%20API.md
我认为 ResolveVersionSupportByRouteConstraint 方法可能有误,请参阅:https://github.com/domaindrivendev/Swashbuckle/issues/197#issuecomment-75288894
你可以找到例子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(确保您传递了 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);
}
}
}
如何配置 swashbuckle
以使用 Aspnet API
verisoning?
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")]。当我用邮递员打 api/v1/users 时,呼叫有效,但我不知道如何使用 Swashbuckle/Swagger.
我希望我的 swagger 文档看起来像 asp.net 核心 api 样板的示例,除了我在 owin 启动 class 中使用 Owin 而不是 .net 核心: https://github.com/ASP-NET-Core-Boilerplate/Templates/blob/master/MVC%206%20API.md
我认为 ResolveVersionSupportByRouteConstraint 方法可能有误,请参阅:https://github.com/domaindrivendev/Swashbuckle/issues/197#issuecomment-75288894
你可以找到例子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(确保您传递了 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);
}
}
}