Skip to content

Commit

Permalink
Merge pull request #715 from SteveDunn/swashbuckle-registration
Browse files Browse the repository at this point in the history
Improve naming of Swashbuckle registrations
  • Loading branch information
SteveDunn authored Nov 23, 2024
2 parents 954c14a + e318af6 commit 5d1e289
Show file tree
Hide file tree
Showing 20 changed files with 80 additions and 70 deletions.
12 changes: 7 additions & 5 deletions docs/site/Writerside/topics/how-to/Use-in-Swagger.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Use in Swagger/OpenAPI

You can use the value objects generated by Vogen as parameters in ASP.NET Core Web API endpoints.
When an endpoint is run, the .NET runtime will notice the `TypeConverter` that is generated by default, and use that to try
When an endpoint is run, the .NET runtime will notice the `TypeConverter` that is generated by default and use that to try
to convert the daa from the request (e.g. `string` or `int`) to the value object.

Front end tools, such as Swagger, use an OpenAPI specification to describe the endpoints and the types used in those endpoints. By default, the value objects generated for the OpenAPI document are specified as `object`. For example, for this endpoint:
Expand Down Expand Up @@ -29,11 +29,13 @@ Both ways include setting a parameter in Vogen's global config:

The choices are: `GenerateSwashbuckleMappingExtensionMethod` or `GenerateSwashbuckleSchemaFilter`

The extension method mechanism is preferable to the schema filter mechanism, as the schema filter uses Reflection at runtime, which is unavailable when using AOT (Ahead-Of-Time).
The extension method mechanism is preferable to the schema filter mechanism, as the schema filter uses Reflection at runtime, which is unavailable when using AOT (Ahead-Of-Time).

This will create a class named `VogenSwashbuckleExtensions` without a namespace (so it'll be in the global namespaces). The class will contain an extension method named `MapVogenTypesInMyWebApp` (`MyWebApp` is the name of your app with illegal characters removed, e.g. `MyApp.Core` will become `MyAppCore`)

The extension method that is generated looks like this:
```C#
static SwaggerGenOptions MapVogenTypes(this SwaggerGenOptions o)
SwaggerGenOptions MapVogenTypesInMyWebApp(this SwaggerGenOptions o)
{
o.MapType<Celcius>(() => new OpenApiSchema { Type = "number" });
o.MapType<City>(() => new OpenApiSchema { Type = "string" });
Expand All @@ -43,12 +45,12 @@ static SwaggerGenOptions MapVogenTypes(this SwaggerGenOptions o)
You register it like this:

```C#
builder.Services.AddSwaggerGen(opt => opt.MapVogenTypes());
builder.Services.AddSwaggerGen(opt => opt.MapVogenTypesInMyWebApp());
```

<note>
If your value objects are defined in another project, that project will also need assembly-level Vogen configuration.
Your other project will then emit a source generated extension method named `MapVogenTypes`.
Your other project will then emit a source-generated extension method named `MapVogenTypes`.
Because there are now two extension methods with the same signature, you'll need to call them explicitly, e.g.

```c#
Expand Down
5 changes: 2 additions & 3 deletions samples/WebApplication/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@
{
// the following extension method is available if you specify `GenerateSwashbuckleMappingExtensionMethod` - as shown above

//opt.MapVogenTypes();
WebApplication.VogenSwashbuckleExtensions.MapVogenTypes(opt);
WebApplication.Shared.VogenSwashbuckleExtensions.MapVogenTypes(opt);
opt.MapVogenTypesInWebApplication();
opt.MapVogenTypesInWebApplicationShared();

// the following schema filter is generated if you specify GenerateSwashbuckleSchemaFilter as shown above
// opt.SchemaFilter<MyVogenSchemaFilter>();
Expand Down
23 changes: 10 additions & 13 deletions src/Vogen/GenerateCodeForOpenApiSchemaCustomization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Vogen.Types;

namespace Vogen;

Expand All @@ -15,22 +16,22 @@ public static void WriteIfNeeded(VogenConfiguration? globalConfig,
{
var c = globalConfig?.OpenApiSchemaCustomizations ?? VogenConfiguration.DefaultInstance.OpenApiSchemaCustomizations;

var fullNamespace = compilation.Assembly.Name;

var theNamespace = string.IsNullOrEmpty(fullNamespace) ? string.Empty : $"namespace {fullNamespace};";
var projectName = ProjectName.FromAssemblyName(compilation.Assembly.Name);
var inAppendage = string.IsNullOrEmpty(projectName) ? string.Empty : $"In{projectName}";

if (c.HasFlag(OpenApiSchemaCustomizations.GenerateSwashbuckleSchemaFilter))
{
WriteSchemaFilter(context, knownSymbols, theNamespace);
WriteSchemaFilter(context, knownSymbols, inAppendage);
}

if (c.HasFlag(OpenApiSchemaCustomizations.GenerateSwashbuckleMappingExtensionMethod))
{
WriteExtensionMethodMapping(context, workItems, knownSymbols, theNamespace);
WriteExtensionMethodMapping(context, workItems, knownSymbols, inAppendage);
}
}

private static void WriteSchemaFilter(SourceProductionContext context, VogenKnownSymbols knownSymbols, string theNamespace)
private static void WriteSchemaFilter(SourceProductionContext context, VogenKnownSymbols knownSymbols, string inAppendage)
{
if (!IsSwashbuckleReferenced(knownSymbols))
{
Expand All @@ -42,11 +43,9 @@ private static void WriteSchemaFilter(SourceProductionContext context, VogenKnow
{{GeneratedCodeSegments.Preamble}}
{{theNamespace}}
using System.Reflection;
public class VogenSchemaFilter : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
public class VogenSchemaFilter{{inAppendage}} : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
{
private const BindingFlags _flags = BindingFlags.Public | BindingFlags.Instance;
Expand Down Expand Up @@ -107,7 +106,7 @@ private static void TryCopyPublicProperties<T>(T oldObject, T newObject) where T
private static void WriteExtensionMethodMapping(SourceProductionContext context,
List<VoWorkItem> workItems,
VogenKnownSymbols knownSymbols,
string theNamespace)
string inAppendage)
{
if (!IsSwashbuckleReferenced(knownSymbols))
{
Expand All @@ -119,11 +118,9 @@ private static void WriteExtensionMethodMapping(SourceProductionContext context,
{{GeneratedCodeSegments.Preamble}}
{{theNamespace}}
public static class VogenSwashbuckleExtensions
{
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypes(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypes{{inAppendage}}(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
{
{{MapWorkItems(workItems)}}
Expand Down
20 changes: 20 additions & 0 deletions src/Vogen/Types/ProjectName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Vogen.Types;

internal class ProjectName
{
private ProjectName(string value) => Value = value;

public static ProjectName FromAssemblyName(string assemblyName)
{
assemblyName = assemblyName.Replace(".", "");
assemblyName = assemblyName.Replace(",", "");
assemblyName = assemblyName.Replace(" ", "");

return new(assemblyName);
}

public string Value { get; }

public static implicit operator string(ProjectName name) => name.Value;
public override string ToString() => Value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591

namespace generator;

public static class VogenSwashbuckleExtensions
{
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypes(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypesIngenerator(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
{
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyLongNamespace.Vo>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "integer", Format = "int32", Nullable = false });
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<global::System.Nullable<MyLongNamespace.Vo>>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "integer", Format = "int32", Nullable = true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591

namespace generator;

public static class VogenSwashbuckleExtensions
{
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypes(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypesIngenerator(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
{
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyLongNamespace.Vo>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "string", Format = "uuid", Nullable = false });
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<global::System.Nullable<MyLongNamespace.Vo>>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "string", Format = "uuid", Nullable = true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
#pragma warning disable CS8669, CS8632
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591
namespace generator;
using System.Reflection;

public class VogenSchemaFilter : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
public class VogenSchemaFilterIngenerator : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
{
private const BindingFlags _flags = BindingFlags.Public | BindingFlags.Instance;
public void Apply(global::Microsoft.OpenApi.Models.OpenApiSchema schema, global::Swashbuckle.AspNetCore.SwaggerGen.SchemaFilterContext context)
Expand Down Expand Up @@ -92,11 +91,9 @@ public class VogenSchemaFilter : global::Swashbuckle.AspNetCore.SwaggerGen.ISche
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591

namespace generator;

public static class VogenSwashbuckleExtensions
{
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypes(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypesIngenerator(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
{
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyLongNamespace.Vo>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "integer", Format = "int32", Nullable = false });
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<global::System.Nullable<MyLongNamespace.Vo>>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "integer", Format = "int32", Nullable = true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
#pragma warning disable CS8669, CS8632
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591
namespace generator;
using System.Reflection;

public class VogenSchemaFilter : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
public class VogenSchemaFilterIngenerator : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
{
private const BindingFlags _flags = BindingFlags.Public | BindingFlags.Instance;
public void Apply(global::Microsoft.OpenApi.Models.OpenApiSchema schema, global::Swashbuckle.AspNetCore.SwaggerGen.SchemaFilterContext context)
Expand Down Expand Up @@ -92,11 +91,9 @@ public class VogenSchemaFilter : global::Swashbuckle.AspNetCore.SwaggerGen.ISche
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591

namespace generator;

public static class VogenSwashbuckleExtensions
{
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypes(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypesIngenerator(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
{
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyVoInt>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "integer", Format = "int32", Nullable = false });
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyVoFloat>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "number", Nullable = false });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591

namespace generator;

public static class VogenSwashbuckleExtensions
{
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypes(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypesIngenerator(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
{
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyVoInt>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "integer", Format = "int32", Nullable = false });
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyVoFloat>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "number", Nullable = false });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
#pragma warning disable CS8669, CS8632
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591
namespace generator;
using System.Reflection;

public class VogenSchemaFilter : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
public class VogenSchemaFilterIngenerator : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
{
private const BindingFlags _flags = BindingFlags.Public | BindingFlags.Instance;
public void Apply(global::Microsoft.OpenApi.Models.OpenApiSchema schema, global::Swashbuckle.AspNetCore.SwaggerGen.SchemaFilterContext context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
#pragma warning disable CS8669, CS8632
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591
namespace generator;
using System.Reflection;

public class VogenSchemaFilter : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
public class VogenSchemaFilterIngenerator : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
{
private const BindingFlags _flags = BindingFlags.Public | BindingFlags.Instance;
public void Apply(global::Microsoft.OpenApi.Models.OpenApiSchema schema, global::Swashbuckle.AspNetCore.SwaggerGen.SchemaFilterContext context)
Expand Down Expand Up @@ -92,11 +91,9 @@ public class VogenSchemaFilter : global::Swashbuckle.AspNetCore.SwaggerGen.ISche
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591

namespace generator;

public static class VogenSwashbuckleExtensions
{
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypes(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypesIngenerator(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
{
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyNamespace.MyVoInt>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "integer", Format = "int32", Nullable = false });
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyNamespace.MyVoFloat>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "number", Nullable = false });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
#pragma warning disable CS8669, CS8632
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591
namespace generator;
using System.Reflection;

public class VogenSchemaFilter : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
public class VogenSchemaFilterIngenerator : global::Swashbuckle.AspNetCore.SwaggerGen.ISchemaFilter
{
private const BindingFlags _flags = BindingFlags.Public | BindingFlags.Instance;
public void Apply(global::Microsoft.OpenApi.Models.OpenApiSchema schema, global::Swashbuckle.AspNetCore.SwaggerGen.SchemaFilterContext context)
Expand Down Expand Up @@ -92,11 +91,9 @@ public class VogenSchemaFilter : global::Swashbuckle.AspNetCore.SwaggerGen.ISche
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591

namespace generator;

public static class VogenSwashbuckleExtensions
{
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypes(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypesIngenerator(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
{
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyVoInt>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "integer", Format = "int32", Nullable = false });
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyVoFloat>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "number", Nullable = false });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591

namespace generator;

public static class VogenSwashbuckleExtensions
{
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypes(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypesIngenerator(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
{
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<@double.MyVoInt>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "integer", Format = "int32", Nullable = false });
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<@double.MyVoFloat>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "number", Nullable = false });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@
// Suppress warnings about CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
#pragma warning disable CS1591

namespace generator;

public static class VogenSwashbuckleExtensions
{
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypes(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
public static global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions MapVogenTypesIngenerator(this global::Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenOptions o)
{
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyNamespace.MyVoInt>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "integer", Format = "int32", Nullable = false });
global::Microsoft.Extensions.DependencyInjection.SwaggerGenOptionsExtensions.MapType<MyNamespace.MyVoFloat>(o, () => new global::Microsoft.OpenApi.Models.OpenApiSchema { Type = "number", Nullable = false });
Expand Down
Loading

0 comments on commit 5d1e289

Please sign in to comment.