Hopefully somebody has tried something similar with a versioned API in MVC 6 and Swagger to display documentation about the different versions.
I am using the recommended API versioning in MVC 6 as per this ASP.NET 5 repository. The only change I have made is the GetVersion method to read the api version from the request's custom http header:
//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;
}
and I have a controller like this:
[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;
}
}
The versioning happens with a custom http header so that
GET /api/tags
Content-Type: application/json
will hit the GetTags() action by default as no header has been specified and the
GET /api/tags
api-version: 2
Content-Type: application/json
will hit the GetTagsV2() action.
I have added Swagger UI and Swagger GEN libraries following steps at this blog so in my project.json
I have de following dependencies:
"Swashbuckle.SwaggerGen": "6.0.0-rc1-final",
"Swashbuckle.SwaggerUi": "6.0.0-rc1-final"
Then in my Startup.cs I add Swagger to the pipeline with
//inside Configure(IApplicationBuilder app)
app.UseSwaggerGen();
app.UseSwaggerUi();
and I configure Swagger as follows:
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"]));
});
}
The problem is that I don't know how to get from the description (which is an instance of Microsoft.AspNet.Mvc.ApiExplorer.ApiDescription) the necessary information to know whether that given action has to be displayed in Swagger UI or not depending on the specified version. Any tip would be greatly appreciated. It would help to understand how the this ASP.NET 5 repository implementation for versioning works because I still don't understand it well and cannot find a good explanation on how the action constraints work.
PS: This stackoverflow question helped me implement the versioning with MVC 6 but I couldn't find much about how Swagger would integrate with this way of versioning an API.