Search code examples
asp.net-coreswagger

Include possible values of enum in Asp.net Swagger Schemas


In our ASP.net Core web API, our DTO's have string properties of which the valid values are defined in enums. (We plan to change the type of these properties to the corresponding enums, but for now this is not possible.)

To the benefit of our API consumers, we would like to have the Swagger UI (Swashbuckle.AspNetCore) show the possible values of these enums. Can I configure Swagger to have these enum values show in the schema (separately or in the corresponding DTO schema) without changing the type of the properties?

public class FooDTO
{
    public int Id {get; set;}
    public string Color {get; set;} // Only has values of FooColor
    // ...
}


public enum FooColor
{
    Purple,
    Blue,
    Pink
}

I'd like the FooColor values to be shown in the Swagger UI schema or anywhere at all.


Solution

  • Implementing the following ISchemaFilter worked for me. Note: my Json serialises camelCasing. Which is why I added formattedPropertyName, adjust to your needs.

    using Microsoft.OpenApi.Any;
    using Microsoft.OpenApi.Models;
    using Swashbuckle.AspNetCore.SwaggerGen;
    
    
    public class EnumSchemaFilter : ISchemaFilter
    {
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            // Check if the property is of type string and has a corresponding enum
            foreach (var property in context.Type.GetProperties().Where(p => p.PropertyType == typeof(string)))
            {
                var matchedConfig = GetEnumTypeAndName.FirstOrDefault(x => x.specifiedClass == context.Type
                    && x.specifiedPropertyName == property.Name);
    
                if (matchedConfig == default)
                    continue;
    
                // Get the enum type for the property
                Type enumType = matchedConfig.enumType;
                string formattedPropertyName = System.Text.Json.JsonNamingPolicy.CamelCase.ConvertName(property.Name);
    
                // Get the enum values and add them to the schema
                var enumValues = Enum.GetNames(enumType)
                    .Select(name => new OpenApiString(name))
                    .ToList<IOpenApiAny>();
    
                schema.Properties[formattedPropertyName].Enum = enumValues;
    
            }
        }
    
        private static List<(Type specifiedClass, string specifiedPropertyName, Type enumType)> GetEnumTypeAndName
        {
            get
            {
                {
                    return new List<(Type, string, Type)>() {
                        (typeof(FooDTO), nameof(FooDTO.Color), typeof(FooColor))
                    };
                }
            }
        }
    }
    

    And then in Program.cs or Startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    
            // Register the custom schema filter
            c.SchemaFilter<EnumSchemaFilter>();
        });
    }