Skip to content

Commit

Permalink
Update to fix swagger docs after versioning
Browse files Browse the repository at this point in the history
  • Loading branch information
shawnwildermuth committed Mar 4, 2024
1 parent 503c34c commit 4796889
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 2 deletions.
4 changes: 3 additions & 1 deletion src/Data/Fakers/TicketFaker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ protected TicketFaker()
.RuleFor(t => t.WorkPerformed, f => f.Hacker.Phrase())
.RuleFor(t => t.EmployeeId, f => _employees.ElementAt(f.Random.Number(0, 9)).Id)
.RuleFor(t => t.ProjectId, f => _projects.ElementAt(f.Random.Number(0, 24)).Id)
.RuleFor(t => t.BillingRate, f => _employees.ElementAt(f.Random.Number(0, 9)).BillingRate);
.RuleFor(t => t.BillingRate, f => _employees.ElementAt(f.Random.Number(0, 9)).BillingRate)
.RuleFor(t => t.Date, (Faker f) => f.Date.Past());
;
}

public static List<Ticket> Generate() => new TicketFaker().Generate(100);
Expand Down
29 changes: 28 additions & 1 deletion src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
using System.Reflection;
using RestDesign.Services;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Options;
using Swashbuckle.AspNetCore.SwaggerGen;

var builder = WebApplication.CreateBuilder(args);

Expand Down Expand Up @@ -70,6 +72,27 @@
svcs.AddSwaggerGen(o =>
{
o.EnableAnnotations();
o.SwaggerDoc("1.0", new Microsoft.OpenApi.Models.OpenApiInfo() { Title = "Api version 1", Version = "1.0", Description = "Original Version." });
o.SwaggerDoc("2.0", new Microsoft.OpenApi.Models.OpenApiInfo() { Title = "Api version 2", Version = "2.0", Description = "Updated Version." });

o.OperationFilter<SwaggerParameterFilters>();
o.DocumentFilter<SwaggerVersionMapping>();

o.DocInclusionPredicate((version, desc) =>
{
var metadata = desc.ActionDescriptor.EndpointMetadata;

var versionData = metadata.FirstOrDefault(i => i.GetType() == typeof(ApiVersionMetadata));
if (versionData is null) return true; // no metadata so it's fine
var versionNumber = double.Parse(version);
var data = ((ApiVersionMetadata)versionData).MappingTo(new ApiVersion(versionNumber));
if (data == ApiVersionMapping.Explicit)
{
return true;
}

return false;
});
});

var app = builder.Build();
Expand All @@ -92,7 +115,11 @@
app.UseStaticFiles();

app.UseSwagger();
app.UseSwaggerUI();
app.UseSwaggerUI(opt =>
{
opt.SwaggerEndpoint($"/swagger/1.0/swagger.json", $"v1.0");
opt.SwaggerEndpoint($"/swagger/2.0/swagger.json", $"v2.0");
});

app.UseRouting();

Expand Down
94 changes: 94 additions & 0 deletions src/Services/SwaggerUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using Asp.Versioning;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace RestDesign.Services;

public class SwaggerConfig
{
public enum VersioningType
{
None, CustomHeader, QueryString, AcceptHeader
}

public static String QueryStringParam { get; private set; } = "";
public static String CustomHeaderParam { get; private set; } = "";
public static String AcceptHeaderParam { get; private set; } = "";

public static VersioningType CurrentVersioningMethod = VersioningType.None;

public static void UseCustomHeaderApiVersion(string parameterName)
{
CurrentVersioningMethod = VersioningType.CustomHeader;
CustomHeaderParam = parameterName;
}

public static void UseQueryStringApiVersion()
{
QueryStringParam = "api-version";
CurrentVersioningMethod = VersioningType.QueryString;
}
public static void UseQueryStringApiVersion(string parameterName)
{
CurrentVersioningMethod = VersioningType.QueryString;
QueryStringParam = parameterName;
}
public static void UseAcceptHeaderApiVersion(String paramName)
{
CurrentVersioningMethod = VersioningType.AcceptHeader;
AcceptHeaderParam = paramName;
}
}

public class SwaggerParameterFilters : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
try
{
var maps = context.MethodInfo.GetCustomAttributes(true).OfType<MapToApiVersionAttribute>().SelectMany(attr => attr.Versions).ToList();
var version = maps[0].MajorVersion;
if (SwaggerConfig.CurrentVersioningMethod == SwaggerConfig.VersioningType.CustomHeader && !context.ApiDescription.RelativePath!.Contains("{version}"))
{
operation.Parameters.Add(new OpenApiParameter { Name = SwaggerConfig.CustomHeaderParam, In = ParameterLocation.Header, Required = false, Schema = new OpenApiSchema { Type = "String", Default = new OpenApiString(version.ToString()) } });
}
else if (SwaggerConfig.CurrentVersioningMethod == SwaggerConfig.VersioningType.QueryString && !context.ApiDescription.RelativePath!.Contains("{version}"))
{
operation.Parameters.Add(new OpenApiParameter { Name = SwaggerConfig.QueryStringParam, In = ParameterLocation.Query, Schema = new OpenApiSchema { Type = "String", Default = new OpenApiString(version.ToString()) } });
}
else if (SwaggerConfig.CurrentVersioningMethod == SwaggerConfig.VersioningType.AcceptHeader && !context.ApiDescription.RelativePath!.Contains("{version}"))
{

operation.Parameters.Add(new OpenApiParameter { Name = "Accept", In = ParameterLocation.Header, Required = false, Schema = new OpenApiSchema { Type = "String", Default = new OpenApiString($"application/json;{SwaggerConfig.AcceptHeaderParam}=" + version.ToString()) } });

}

var versionParameter = operation.Parameters.Single(p => p.Name == "version");

if (versionParameter != null)
{
operation.Parameters.Remove(versionParameter);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}

public class SwaggerVersionMapping : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
var pathLists = new OpenApiPaths();
IDictionary<string, OpenApiPaths> paths = new Dictionary<string, OpenApiPaths>();
var version = swaggerDoc.Info.Version.Replace("v", "").Replace("version", "").Replace("ver", "").Replace(" ", "");
foreach (var path in swaggerDoc.Paths)
{
pathLists.Add(path.Key.Replace("v{version}", swaggerDoc.Info.Version), path.Value);
}
swaggerDoc.Paths = pathLists;
}
}

0 comments on commit 4796889

Please sign in to comment.