Last active
June 10, 2020 11:58
-
-
Save Alezis/bab8b559d0d8800c994d065db03ab53e to your computer and use it in GitHub Desktop.
Swashbuckle.AspNetCore AND Microsoft.AspNetCore.Mvc.Versioning
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Reflection; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore.Builder; | |
using Microsoft.AspNetCore.Hosting; | |
using Microsoft.AspNetCore.Mvc; | |
using Microsoft.Extensions.Configuration; | |
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.Logging; | |
using Swashbuckle.AspNetCore.Swagger; | |
using Swashbuckle.AspNetCore.SwaggerGen; | |
namespace VersionsSwagger | |
{ | |
public class Startup | |
{ | |
public Startup(IHostingEnvironment env) | |
{ | |
var builder = new ConfigurationBuilder() | |
.SetBasePath(env.ContentRootPath) | |
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) | |
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) | |
.AddEnvironmentVariables(); | |
Configuration = builder.Build(); | |
} | |
public IConfigurationRoot Configuration { get; } | |
public void ConfigureServices(IServiceCollection services) | |
{ | |
services.AddMvc(); | |
// Configure versions | |
services.AddApiVersioning(o => | |
{ | |
o.AssumeDefaultVersionWhenUnspecified = true; | |
o.DefaultApiVersion = new ApiVersion(1, 0); | |
}); | |
// Configure swagger | |
services.AddSwaggerGen(options => | |
{ | |
// Specify two versions | |
options.SwaggerDoc("v1", | |
new Info() | |
{ | |
Version = "v1", | |
Title = "v1 API", | |
Description = "v1 API Description", | |
TermsOfService = "Terms of usage v1" | |
}); | |
options.SwaggerDoc("v2", | |
new Info() | |
{ | |
Version = "v2", | |
Title = "v2 API", | |
Description = "v2 API Description", | |
TermsOfService = "Terms of usage v2" | |
}); | |
// This call remove version from parameter, without it we will have version as parameter | |
// for all endpoints in swagger UI | |
options.OperationFilter<RemoveVersionFromParameter>(); | |
// This make replacement of v{version:apiVersion} to real version of corresponding swagger doc. | |
options.DocumentFilter<ReplaceVersionWithExactValueInPath>(); | |
// This on used to exclude endpoint mapped to not specified in swagger version. | |
// In this particular example we exclude 'GET /api/v2/Values/otherget/three' endpoint, | |
// because it was mapped to v3 with attribute: MapToApiVersion("3") | |
options.DocInclusionPredicate((version, desc) => | |
{ | |
var versions = desc.ControllerAttributes() | |
.OfType<ApiVersionAttribute>() | |
.SelectMany(attr => attr.Versions); | |
var maps = desc.ActionAttributes() | |
.OfType<MapToApiVersionAttribute>() | |
.SelectMany(attr => attr.Versions) | |
.ToArray(); | |
return versions.Any(v => $"v{v.ToString()}" == version) && (maps.Length == 0 || maps.Any(v => $"v{v.ToString()}" == version)); | |
}); | |
}); | |
} | |
public class RemoveVersionFromParameter : IOperationFilter | |
{ | |
public void Apply(Operation operation, OperationFilterContext context) | |
{ | |
var versionParameter = operation.Parameters.Single(p => p.Name == "version"); | |
operation.Parameters.Remove(versionParameter); | |
} | |
} | |
public class ReplaceVersionWithExactValueInPath : IDocumentFilter | |
{ | |
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context) | |
{ | |
swaggerDoc.Paths = swaggerDoc.Paths | |
.ToDictionary( | |
path => path.Key.Replace("v{version}", swaggerDoc.Info.Version), | |
path => path.Value | |
); | |
} | |
} | |
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | |
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) | |
{ | |
loggerFactory.AddConsole(Configuration.GetSection("Logging")); | |
loggerFactory.AddDebug(); | |
app.UseSwagger(); | |
app.UseSwaggerUI(c => | |
{ | |
c.SwaggerEndpoint($"/swagger/v2/swagger.json", $"v2"); | |
c.SwaggerEndpoint($"/swagger/v1/swagger.json", $"v1"); | |
}); | |
app.UseMvc(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore.Mvc; | |
namespace VersionsSwagger.Controllers | |
{ | |
[Route("api/v{version:apiVersion}/[controller]")] | |
[ApiVersion("1")] | |
[ApiVersion("2")] | |
public class ValuesController : Controller | |
{ | |
// GET api/values | |
[HttpGet] | |
public IEnumerable<string> Get() | |
{ | |
return new string[] { "value1", "value2" }; | |
} | |
// GET api/values/5 | |
[HttpGet("{id}")] | |
public string Get(int id) | |
{ | |
return "value"; | |
} | |
// POST api/values | |
[HttpPost] | |
public void Post([FromBody]string value) | |
{ | |
} | |
// PUT api/values/5 | |
[HttpPut("{id}")] | |
public void Put(int id, [FromBody]string value) | |
{ | |
} | |
// DELETE api/values/5 | |
[HttpDelete("{id}")] | |
public void Delete(int id) | |
{ | |
} | |
[HttpGet("otherget/one")] | |
[MapToApiVersion("2")] | |
public IEnumerable<string> Get2() | |
{ | |
return new string[] { "value1", "value2" }; | |
} | |
/// <summary> | |
/// THIS ONE WILL BE EXCLUDED FROM SWAGGER Ui, BECAUSE v3 IS NOT SPECIFIED. 'DocInclusionPredicate' MAKES THE | |
/// TRICK | |
/// </summary> | |
/// <returns></returns> | |
[HttpGet("otherget/three")] | |
[MapToApiVersion("3")] | |
public IEnumerable<string> Get3() | |
{ | |
return new string[] { "value1", "value2" }; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment