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

```C#
[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:

<img border-effect="rounded" alt="swagger-json-parameter.png" src="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:

```C#
[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).

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#
SwaggerGenOptions MapVogenTypesInMyWebApp(this SwaggerGenOptions o)
{
    o.MapType<Celcius>(() => new OpenApiSchema { Type = "number" });
    o.MapType<City>(() => new OpenApiSchema { Type = "string" });
    ...
```

You register it like this:

```C#
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`.
Because there are now two extension methods with the same signature, you'll need to call them explicitly, e.g.

```c#
    WebApp.VogenSwashbuckleExtensions.MapVogenTypes(opt);
    WebApp.Shared.VogenSwashbuckleExtensions.MapVogenTypes(opt);
```
</note>

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

```C#
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:

```C#
builder.Services.AddSwaggerGen(opt => 
    opt.SchemaFilter<VogenSchemaFilter>());
```
Many thanks to [Vitalii Mikhailov](https://github.com/Aragas) for contributing the schema filter code.
