昂首阔步找不到ApiVersion版本的动作 [英] Swagger not finding ApiVersion-ed actions
问题描述
我正在ASP.NET Core中构建Web API,并正在尝试使用多个版本.我正在按照以下说明为每个版本创建Swagger文档: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/README.md#customize-the-action-selection-process
I'm building a Web API in ASP.NET Core and am experimenting with multiple versions. I am creating Swagger docs for each version following these instructions: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/README.md#customize-the-action-selection-process
我为同一个动作定义了2个版本,如下所示:
I have 2 versions of the same action defined like this:
namespace Web.Api
{
[ApiController]
[Area("api")]
[Route("[area]/[controller]")]
public abstract class MyApiControllerBase : ControllerBase
{
}
}
namespace Web.Api.V1
{
public class TestController : MyApiControllerBase
{
[HttpGet]
[ApiVersion("1.0")]
public IActionResult Get()
{
return Ok("Version 1.0 endpoint.");
}
}
}
namespace Web.Api.V2
{
public class TestController : MyApiControllerBase
{
[HttpGet]
[ApiVersion("2.0")]
public IActionResult Get()
{
return Ok("Version 2.0 endpoint.");
}
}
}
我的Swagger Gen在 Startup.cs
中配置如下:
And my Swagger Gen configured like this in Startup.cs
:
services.AddSwaggerGen(options =>
{
options.DocInclusionPredicate((docName, apiDesc) =>
{
if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo))
{
return false;
}
IEnumerable<ApiVersion> versions = methodInfo.DeclaringType
.GetCustomAttributes(true)
.OfType<ApiVersionAttribute>()
.SelectMany(a => a.Versions);
return versions.Any(v => $"v{v.ToString()}" == docName);
});
options.SwaggerDoc("v1.0", new OpenApiInfo { Title = "My API", Version = "v1.0" });
options.SwaggerDoc("v2.0", new OpenApiInfo { Title = "My API", Version = "v2.0" });
});
但是,当我访问Swagger UI时,它说规范中未定义任何操作!"对于v1.0和v2.0.如果在加载Swagger文档时检查 DocInclusionPredicate
,似乎未选择 ApiVersion
属性,从而解释了为什么未将其包含在文档中.例如,当 Web.Api.V2.TestController.Get
作为 apiDesc
参数传递时,这就是对属性的发现:
However when I visit my Swagger UI it says "No operations defined in spec!" for both v1.0 and v2.0. If I inspect the DocInclusionPredicate
when loading the Swagger doc it appears that the ApiVersion
Attribute isn't being picked up and thus explains why they aren't included in the docs. For example, when Web.Api.V2.TestController.Get
is passed as the apiDesc
argument, this is what is found for Attributes:
ApiControllerAttribute , AreaAttribute
, RouteAttribute
和 ControllerAttribute
.所有这些都是基类上的属性,而不是直接在 TestController
或 Get()
操作本身上.
Only ApiControllerAttribute
, AreaAttribute
, RouteAttribute
, and ControllerAttribute
are found. All of these are Attributes on base classes, not directly on the TestController
or Get()
action itself.
推荐答案
对于asp.net core 3.0,您可以按照以下步骤操作:
For asp.net core 3.0,you could follow the following steps:
1.安装 Swashbuckle.AspNetCore 5.0.0
1.Install Swashbuckle.AspNetCore 5.0.0
2.安装 Microsoft.AspNetCore.Mvc版本4.0.0
2.Install Microsoft.AspNetCore.Mvc.Versioning 4.0.0
3.安装 Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer 4.0.0
3.Install Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer 4.0.0
4.如下更改控制器( ApiVersion
需要在控制器上声明)
4.Change your controller like below(ApiVersion
needs to be declared on controller):
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
public class TestController : MyApiControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Version 1.0 endpoint.");
}
}
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("2.0")]
public class TestController : MyApiControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Version 2.0 endpoint.");
}
}
5.Startup.cs(请注意,您需要使用 services.AddVersionedApiExplorer
并设置 options.SubstituteApiVersionInUrl = true
告诉大摇大摆来替换控制器路由中的版本并配置api版本:):
5.Startup.cs(Note that you need to use services.AddVersionedApiExplorer
and set options.SubstituteApiVersionInUrl=true
to tell swagger to replace the version in the controller route and configure the api version: ):
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddApiVersioning(o => {
o.ReportApiVersions = true;
o.AssumeDefaultVersionWhenUnspecified = true;
o.DefaultApiVersion = new ApiVersion(1, 0);
});
services.AddVersionedApiExplorer(o =>
{
o.GroupNameFormat = "'v'VVV";
o.SubstituteApiVersionInUrl = true;
});
services.AddSwaggerGen(options =>
{
options.DocInclusionPredicate((docName, apiDesc) =>
{
if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo))
{
return false;
}
IEnumerable<ApiVersion> versions = methodInfo.DeclaringType
.GetCustomAttributes(true)
.OfType<ApiVersionAttribute>()
.SelectMany(a => a.Versions);
return versions.Any(v => $"v{v.ToString()}" == docName);
});
options.SwaggerDoc("v1.0", new OpenApiInfo { Title = "My API", Version = "v1.0" });
options.SwaggerDoc("v2.0", new OpenApiInfo { Title = "My API", Version = "v2.0" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseApiVersioning();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1.0/swagger.json", "V1 Docs");
c.SwaggerEndpoint("/swagger/v2.0/swagger.json", "V2 Docs");
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
这篇关于昂首阔步找不到ApiVersion版本的动作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!