问题描述
请帮帮我,一开始看起来很容易,现在我在项目中迟到了:
Please help me with this, it looked easy at first, now I'm late in the project:
我正在尝试为 ASP.NET WebApi 项目以及 Swagger 设置 API 版本控制.API 版本控制工作正常,调用不同的版本返回正确的结果(见下文).
I'm trying to setup API versioning for a ASP.NET WebApi project, along with Swagger. The API versioning works fine, calling different versions returns the correct results (see below).
相反,Swagger 无法同时提供这两个版本.在调试时,我注意到当在 SwaggerConfig.cs 中调用 c.MultipleApiVersions(...)
时,apiDesc.ActionDescriptor.ControllerDescriptor
报告的控制器始终是 PingController
并且从不 Ping11Controller
.
On the contrary, Swagger fails to serve both versions. While debugging, I noticed that when c.MultipleApiVersions(...)
gets called in SwaggerConfig.cs, the controller reported by apiDesc.ActionDescriptor.ControllerDescriptor
is always PingController
and never Ping11Controller
.
有人可以指出需要做些什么来解决这个问题并让 Swagger 也适用于这两个版本吗?
Can somebody point out what needs to be done to solve this and have Swagger also work for both versions?
以下是 API 版本控制的代码和证明工作正常,而 Swagger 仅适用于 v1.0.
Below, the code and proof of API versioning working fine while Swagger working only for v1.0.
谢谢!
调用 API v1.0 有效:
调用 API v1.1 也可以:
Swagger for v1.0 很好:(http://localhost:50884/v1.0/swagger)
{
"swagger":"2.0",
"info":{
"version":"v1.0",
"title":"My API v1.0"
},
"host":"localhost:50884",
"schemes":[
"http"
],
"paths":{
"/api/ping":{
"get":{
"tags":[
"Ping"
],
"summary":"Get a pong.",
"operationId":"GetAPong",
"consumes":[
],
"produces":[
"application/json",
"text/json",
"application/xml",
"text/xml"
],
"responses":{
"200":{
"description":"OK"
},
"404":{
"description":"NotFound"
}
}
}
}
},
"definitions":{
}
}
Swagger for v1.1 为空:(http://localhost:50884/v1.1/swagger)
{
"swagger":"2.0",
"info":{
"version":"v1.1",
"title":"My API v1.1"
},
"host":"localhost:50884",
"schemes":[
"http"
],
"paths":{
},
"definitions":{
}
}
代码
App_StartWebApiConfig.cs:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.AddApiVersioning(options => {
options.ReportApiVersions = true;
});
var constraintResolver = new System.Web.Http.Routing.DefaultInlineConstraintResolver();
constraintResolver.ConstraintMap.Add("apiVersion", typeof(Microsoft.Web.Http.Routing.ApiVersionRouteConstraint));
config.MapHttpAttributeRoutes(constraintResolver);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
App_StartSwaggerConfig.cs:
public class SwaggerConfig
{
static string XmlCommentsFilePath
{
get
{
var basePath = System.AppDomain.CurrentDomain.RelativeSearchPath;
var fileName = typeof(SwaggerConfig).GetTypeInfo().Assembly.GetName().Name + ".xml";
return Path.Combine(basePath, fileName);
}
}
public static void Register()
{
var configuration = GlobalConfiguration.Configuration;
GlobalConfiguration.Configuration.EnableSwagger("{apiVersion}/swagger", c => {
c.OperationFilter<SwaggerDefaultValues>();
c.MultipleApiVersions((System.Web.Http.Description.ApiDescription apiDesc, string targetApiVersion) =>
{
var attr = apiDesc.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<Microsoft.Web.Http.ApiVersionAttribute>().FirstOrDefault();
if (attr == null && (targetApiVersion == "v1" || targetApiVersion == "v1.0")) return true;
var match = (attr != null) && (attr.Versions.FirstOrDefault(v => "v" + v.ToString() == targetApiVersion) != null);
return match;
},
(vc) =>
{
vc.Version("v1.1", "My API v1.1");
vc.Version("v1.0", "My API v1.0");
});
c.IncludeXmlComments(SwaggerConfig.XmlCommentsFilePath);
})
.EnableSwaggerUi(c => {
c.DocExpansion(DocExpansion.List);
c.EnableDiscoveryUrlSelector();
});
}
}
v1.0 和 v1.1 的控制器(位于同一命名空间中)
[ApiVersion("1.0")]
[RoutePrefix("api")]
[ControllerName("Ping")]
public class PingController : ApiController
{
[HttpGet]
[Route("ping")]
[SwaggerOperation("GetAPong")]
[SwaggerResponse(HttpStatusCode.OK)]
[SwaggerResponse(HttpStatusCode.NotFound)]
public string Get()
{
return "Pong v1.0";
}
}
[ApiVersion("1.1")]
[RoutePrefix("api")]
[ControllerName("Ping")]
public class Ping11Controller : ApiController
{
[HttpGet]
[Route("ping")]
[SwaggerOperation("GetAPong")]
[SwaggerResponse(HttpStatusCode.OK)]
[SwaggerResponse(HttpStatusCode.NotFound)]
public string Get()
{
return "Pong v1.1";
}
}
包裹
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net46" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net46" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net46" />
<package id="Microsoft.AspNet.WebApi.Versioning" version="2.1.0" targetFramework="net46" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net46" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.7" targetFramework="net46" />
<package id="Microsoft.IdentityModel.Logging" version="1.1.4" targetFramework="net46" />
<package id="Microsoft.IdentityModel.Tokens" version="5.1.4" targetFramework="net46" />
<package id="Microsoft.Net.Compilers" version="2.3.2" targetFramework="net46" developmentDependency="true" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net46" />
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net46" />
<package id="NLog" version="4.4.12" targetFramework="net46" />
<package id="Swashbuckle" version="5.6.0" targetFramework="net46" />
<package id="Swashbuckle.Core" version="5.6.0" targetFramework="net46" />
<package id="System.IdentityModel.Tokens.Jwt" version="5.1.4" targetFramework="net46" />
<package id="WebActivatorEx" version="2.2.0" targetFramework="net46" />
</packages>
推荐答案
已解决:
- 添加 Microsoft.AspNet.WebApi.Versioning.ApiExplorer 包
使用如下版本的 API 资源管理器(请注意,由于初始化问题,我不得不将代码从 SwaggerConfig.cs 移至 WebApiConfig.cs):
- Adding the Microsoft.AspNet.WebApi.Versioning.ApiExplorer package
Using the versioned API explorer as below (note that I had to move the code from SwaggerConfig.cs in WebApiConfig.cs due to initialization issues):
var apiExplorer = config.AddVersionedApiExplorer(options => {
options.GroupNameFormat = "'v'VVV";
});
var versionSupportResolver = new Func<ApiDescription, string, bool>((apiDescription, version) => apiDescription.GetGroupName() == version);
var versionInfoBuilder = new Action<VersionInfoBuilder>(info => {
foreach (var group in apiExplorer.ApiDescriptions)
{
info.Version(group.Name, $"MyAPI v{group.ApiVersion}");
}
});
config
.EnableSwagger("{apiVersion}/swagger", swagger => {
swagger.OperationFilter<SwaggerDefaultValues>();
swagger.MultipleApiVersions(versionSupportResolver, versionInfoBuilder);
swagger.IncludeXmlComments(WebApiConfig.XmlCommentsFilePath);
})
.EnableSwaggerUi(swaggerUi => {
swaggerUi.EnableDiscoveryUrlSelector();
swaggerUi.DocExpansion(DocExpansion.List);
});
这篇关于Swagger 无法与多个版本的 ASP.NET WebApi 应用程序一起正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!