Несколько версий API с Swagger в MVC 6 при использовании ограничений действия
Надеемся, что кто-то попробовал нечто подобное с версионным API в MVC 6 и Swagger для отображения документации о различных версиях.
Я использую рекомендуемые версии API в MVC 6 в соответствии с этим хранилищем ASP.NET 5. Единственное изменение, которое я сделал, - это метод GetVersion для чтения версии API из пользовательского заголовка http запроса:
//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 / теги
Тип контента: приложение / JSON
по умолчанию выполнит действие GetTags(), поскольку заголовок не указан и
GET / API / теги
api-версия: 2
Тип контента: приложение / JSON
ударит действие GetTagsV2().
В этом блоге я добавил библиотеки 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 или нет, в зависимости от по указанной версии. Любой совет будет принята с благодарностью. Это помогло бы понять, как работает реализация репозитория ASP.NET 5 для управления версиями, потому что я до сих пор плохо понимаю ее и не могу найти хорошего объяснения того, как работают ограничения действия.
PS: Этот вопрос о переполнении стека помог мне реализовать управление версиями с помощью MVC 6, но я не мог найти много информации о том, как Swagger интегрируется с этим способом управления версиями API.
2 ответа
Похоже, у вас есть обычай VersionGet
приписывать. Вы можете использовать это для определения конечных точек v2. Другие конечные точки могут по умолчанию v1 (если это то, что вы хотите).
Вот фрагмент, который я использую. Обратите внимание, что мой пользовательский атрибут называется 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();
}
Мой первый ответ на вопрос здесь, надеюсь, вы найдете его полезным. Приношу свои извинения за плохое форматирование фрагмента кода, но сейчас у меня мало времени.
Вы были почти там, но вы не добавили фильтр для версии в описании. Это работает в моей реализации для следующего формата 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()); } );