Vogen Help

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 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:

[HttpGet("/WeatherForecast/{cityName}")] public IEnumerable<WeatherForecast> Get(CityName cityName) { ... }

You can call this from the Swagger UI (e.g., at http://localhost:5053/WeatherForecast/London) without having to do anything else, but Swagger will show the field as a JSON 'object' instead of the underlying type:

swagger-json-parameter.png

If you're using Swashbuckle to generate your OpenAPI document, then there are two ways to fix this. Both ways include setting a parameter in Vogen's global config:

[assembly: VogenDefaults( openApiSchemaCustomizations: OpenApiSchemaCustomizations.[choices])]

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 that is generated looks like this:

public static SwaggerGenOptions MapVogenTypes(this SwaggerGenOptions o) { o.MapType<Celcius>(() => new OpenApiSchema { Type = "number" }); o.MapType<City>(() => new OpenApiSchema { Type = "string" }); ...

You register it like this:

builder.Services.AddSwaggerGen(opt => opt.MapVogenTypes());

If you decide to use the schema filter, it looks like this:

public class VogenSchemaFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext ctx) { see if it is ValueObjectAttribute * get the underlying type * create a schema object * copy properties from the primitive to the new schema object } }

You register it like this:

builder.Services.AddSwaggerGen(opt => opt.SchemaFilter<VogenSchemaFilter>());

Many thanks to Vitalii Mikhailov for contributing the schema filter code.

Last modified: 16 September 2024