使用动作约束时在 MVC 6 中使用 Swagger 的多个 Api 版本
Posted
技术标签:
【中文标题】使用动作约束时在 MVC 6 中使用 Swagger 的多个 Api 版本【英文标题】:Multiple Api Versions with Swagger in MVC 6 when using action constraints 【发布时间】:2016-04-06 23:25:32 【问题描述】:希望有人尝试过使用 MVC 6 和 Swagger 中的版本化 API 进行类似的操作,以显示有关不同版本的文档。
我根据this ASP.NET 5 repository 在 MVC 6 中使用推荐的 API 版本控制。我所做的唯一更改是从请求的自定义 http 标头中读取 api 版本的 GetVersion 方法:
//in VersionRangeValidator.cs
public static string GetVersion(HttpRequest request)
//return request.Query["version"];
if (!string.IsNullOrWhiteSpace(request.Headers[Constants.CommonRoutingDefinitions.ApiVersionSegmentName]))
return request.Headers[Constants.CommonRoutingDefinitions.ApiVersionSegmentName];
return Constants.CommonRoutingDefinitions.CurrentApiVersion;
我有一个这样的控制器:
[Route("api/[controller]")]
[Produces(Constants.MediaTypeNames.ApplicationJson)]
public class TagsController : Controller
private readonly ITagService _tagService;
public TagsController(ITagService tagService)
_tagService = tagService;
/// <summary>
/// Version 1 by default
/// </summary>
/// <returns>All the tags</returns>
[HttpGet]
[Produces(typeof(IEnumerable<Tag>))]
public IEnumerable<Tag> GetTags()
IEnumerable<Tag> tags = _tagService.GetTags();
return tags;
/// <summary>
/// Version 2
/// </summary>
/// <returns>All the tags V2</returns>
[VersionGet("", versionRange: "[2]")]
public IEnumerable<Tag> GetTagsV2()
IList<Tag> tags = new List<Tag>
new Tag Id = 1, Links = Enumerable.Empty<Link>().ToList(), Name = "Tag version 2"
;
return tags;
版本控制使用自定义 http 标头进行,以便
GET /api/tags
内容类型:application/json
默认情况下会触发 GetTags() 操作,因为没有指定标题并且
GET /api/tags
api版本:2
内容类型:application/json
将触发 GetTagsV2() 操作。
我已经按照this blog 的步骤添加了 Swagger UI 和 Swagger GEN 库,所以在我的 project.json
中我有以下依赖项:
"Swashbuckle.SwaggerGen": "6.0.0-rc1-final",
"Swashbuckle.SwaggerUi": "6.0.0-rc1-final"
然后在我的 Startup.cs 中,我将 Swagger 添加到管道中
//inside Configure(IApplicationBuilder app)
app.UseSwaggerGen();
app.UseSwaggerUi();
我将 Swagger 配置如下:
private void ConfigureSwagger(IServiceCollection services)
services.AddSwaggerGen();
services.ConfigureSwaggerDocument(options =>
options.MultipleApiVersions(new Swashbuckle.SwaggerGen.Info[]
new Swashbuckle.SwaggerGen.Info
Version = "v1",
Title = "MyApp API",
Description = "A RESTful API"
,
new Swashbuckle.SwaggerGen.Info
Version = "v2",
Title = "MyApp API (v2)",
Description = "A RESTful API"
, (description, version) =>
//description is an instance of ApiDescription and
//version is either "v1" or "v2"
//depending on the user choice in swagger UI page
//TODO, how can I know whether the action belongs to v1 or to v2 to return true or false as appropriate?
);
options.OperationFilter(new Swashbuckle.SwaggerGen.XmlComments.ApplyXmlActionComments(Configuration["Documentation:SwaggerDocXml"]));
);
services.ConfigureSwaggerSchema(options =>
options.DescribeAllEnumsAsStrings = true;
options.ModelFilter(new Swashbuckle.SwaggerGen.XmlComments.ApplyXmlTypeComments(Configuration["Documentation:SwaggerDocXml"]));
);
问题是我不知道如何从描述中获取(这是Microsoft.AspNet.Mvc.ApiExplorer.ApiDescription的一个实例)知道是否需要的信息给定的操作是否必须显示在 Swagger UI 中,具体取决于指定的版本。 任何提示将不胜感激。这将有助于理解版本控制的this ASP.NET 5 repository 实现是如何工作的,因为我仍然不太了解它,也找不到关于动作约束如何工作的好的解释。
PS:This *** question 帮助我使用 MVC 6 实现版本控制,但我找不到太多关于 Swagger 如何与这种 API 版本控制方式集成的信息。
【问题讨论】:
你查到真相了吗? 很遗憾我没有。 试试这个github.com/domaindrivendev/Ahoy/tree/master/test/WebSites/… 【参考方案1】:我在这里对一个问题的第一个回答,希望你觉得它有用。我对代码 sn-p 的错误格式表示歉意,但我现在没有时间了。
您快到了,但您没有在说明中添加版本过滤器。这在我的实现中适用于以下 url 格式:
"/v1/Sessions" and "/v3/Sessions"
options.MultipleApiVersions(new Info[]
new Info
Version = "v1",
Title = "your_own",
Description = "Defines the API to access... your_own",
TermsOfService = "your_own",
Contact = new Contact()
Email = "your_own",
Name = "your_own"
,
new Info
Version = "v3",
Title = "your_own",
Description =
"Defines the API to .... your_own",
TermsOfService = "your_own",
Contact = new Contact()
Email = "your_own",
Name = "your_own"
, (description, version) =>
//Here we compare if the version is part of the incoming URI, if yes, show it on swagger page.
return description.RelativePath.ToLower().Contains(version.ToLower()); );
【讨论】:
【参考方案2】:您似乎有一个自定义的VersionGet
属性。您可以使用它来确定 v2 端点。其他端点可能默认为 v1(如果这是您想要的)。
这是我使用的一个 sn-p。请注意,我的自定义属性名为 ApiVersion2
。
public static bool ResolveVersion(ApiDescription apiDesc, string targetApiVersion)
if (targetApiVersion == "v2")
ApiVersion2Attribute v2Attr = apiDesc.ActionDescriptor.GetCustomAttributes<ApiVersion2Attribute>().FirstOrDefault();
if (v2Attr != null)
return true;
if (targetApiVersion == "v1")
return true;
throw new NotSupportedException();
【讨论】:
以上是关于使用动作约束时在 MVC 6 中使用 Swagger 的多个 Api 版本的主要内容,如果未能解决你的问题,请参考以下文章
MVC 4 - 对象引用未设置为对象的实例。当 POST 动作和索引每一行时
何时在 MVC 6 的视图中使用 @await Html.PartialAsync
如何使用格式化程序将参数发送到操作:MVC 中 jqGrid 4.6.0 中的“showlink”