Multiple versions of Api with Swagger in MVC 6 using action restrictions

Hopefully someone tried something similar with the versioned API in MVC 6 and Swagger to display documentation on different versions.

I am using the recommended version control API in MVC 6 on this ASP.NET 5 repository . The only change I made was the GetVersion method to read the api version from the custom HTTP request 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; } } 

Versioning happens with a custom http header to

Get / api / tags

Content-Type: application / json

will result in GetTags () by default, since no header is specified, but

Get / api / tags

api version: 2

Content-Type: application / json

will hit the GetTagsV2 () action.

I added the Swagger UI and Swagger GEN libraries the following steps this blog , so in my project.json I have the 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 the description (which is an instance of Microsoft.AspNet.Mvc.ApiExplorer.ApiDescription) the necessary information to find out whether this action should be displayed in the Swagger user interface or does not depend on the specified version . Any advice would be greatly appreciated. This would help to understand how this ASP.NET 5 repository works for version control, because I still do not understand it and cannot find a good explanation of how action restrictions work.

PS: https : //stackoverflow.com/a/166268/2128/3168/en/css/simple/contentions/357480/... helped me implement version control using MVC 6, but I couldn’t learn much about how Swagger would integrate with this API version control method.

+6
source share
2 answers

My first answer to the question is here, I hope you find it useful. We apologize for the poor formatting of the code snippet, but I have little time on hand.

You were almost there, but you did not add a filter for the version in the description. This works in my implementation for the following URL format:

 "/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
source

It seems you have a custom VersionGet attribute. You can use this to define v2 endpoints. Other endpoints can use v1 by default (if that's what you want).

Here is the snippet I'm using. Please note that my custom attribute is called 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(); } 
+2
source

All Articles