Swagger UI Web Api documentation Present enums as strings?
Solution 1:
Enable globally
From the docs:
httpConfiguration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "A title for your API");
c.DescribeAllEnumsAsStrings(); // this will do the trick
});
Enum/string conversion on particular property
Also, if you want this behavior only on a particular type and property, use the StringEnumConverter:
public class Letter
{
[Required]
public string Content {get; set;}
[Required]
[EnumDataType(typeof(Priority))]
[JsonConverter(typeof(StringEnumConverter))]
public Priority Priority {get; set;}
}
If you're using Newtonsoft and Swashbuckle v5.0.0 or higher
You'll also need this package:
Swashbuckle.AspNetCore.Newtonsoft
And this in your startup:
services.AddSwaggerGenNewtonsoftSupport(); // explicit opt-in - needs to be placed after AddSwaggerGen()
There's docs here: https://github.com/domaindrivendev/Swashbuckle.AspNetCore#systemtextjson-stj-vs-newtonsoft
Solution 2:
For ASP.NET Core 3 with the Microsoft JSON library (System.Text.Json)
In Startup.cs/ConfigureServices():
services
.AddControllersWithViews(...) // or AddControllers() in a Web API
.AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
For ASP.NET Core 3 with the Json.NET (Newtonsoft.Json) library
Install the Swashbuckle.AspNetCore.Newtonsoft
package.
In Startup.cs/ConfigureServices():
services
.AddControllersWithViews(...)
.AddNewtonsoftJson(options =>
options.SerializerSettings.Converters.Add(new StringEnumConverter()));
// order is vital, this *must* be called *after* AddNewtonsoftJson()
services.AddSwaggerGenNewtonsoftSupport();
For ASP.NET Core 2
In Startup.cs/ConfigureServices():
services
.AddMvc(...)
.AddJsonOptions(options =>
options.SerializerSettings.Converters.Add(new StringEnumConverter()));
Pre-ASP.NET Core
httpConfiguration
.EnableSwagger(c =>
{
c.DescribeAllEnumsAsStrings();
});
Solution 3:
So I think I have a similar problem. I'm looking for swagger to generate enums along with the int -> string mapping. The API must accept the int. The swagger-ui matters less, what I really want is code generation with a "real" enum on the other side (android apps using retrofit in this case).
So from my research this ultimately seems to be a limit of the OpenAPI specification which Swagger uses. It's not possible to specify names and numbers for enums.
The best issue I've found to follow is https://github.com/OAI/OpenAPI-Specification/issues/681 which looks like a "maybe soon" but then Swagger would have to be updated, and in my case Swashbuckle as well.
For now my workaround has been to implement a document filter that looks for enums and populates the relevant description with the contents of the enum.
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.DocumentFilter<SwaggerAddEnumDescriptions>();
//disable this
//c.DescribeAllEnumsAsStrings()
SwaggerAddEnumDescriptions.cs:
using System;
using System.Web.Http.Description;
using Swashbuckle.Swagger;
using System.Collections.Generic;
public class SwaggerAddEnumDescriptions : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
// add enum descriptions to result models
foreach (KeyValuePair<string, Schema> schemaDictionaryItem in swaggerDoc.definitions)
{
Schema schema = schemaDictionaryItem.Value;
foreach (KeyValuePair<string, Schema> propertyDictionaryItem in schema.properties)
{
Schema property = propertyDictionaryItem.Value;
IList<object> propertyEnums = property.@enum;
if (propertyEnums != null && propertyEnums.Count > 0)
{
property.description += DescribeEnum(propertyEnums);
}
}
}
// add enum descriptions to input parameters
if (swaggerDoc.paths.Count > 0)
{
foreach (PathItem pathItem in swaggerDoc.paths.Values)
{
DescribeEnumParameters(pathItem.parameters);
// head, patch, options, delete left out
List<Operation> possibleParameterisedOperations = new List<Operation> { pathItem.get, pathItem.post, pathItem.put };
possibleParameterisedOperations.FindAll(x => x != null).ForEach(x => DescribeEnumParameters(x.parameters));
}
}
}
private void DescribeEnumParameters(IList<Parameter> parameters)
{
if (parameters != null)
{
foreach (Parameter param in parameters)
{
IList<object> paramEnums = param.@enum;
if (paramEnums != null && paramEnums.Count > 0)
{
param.description += DescribeEnum(paramEnums);
}
}
}
}
private string DescribeEnum(IList<object> enums)
{
List<string> enumDescriptions = new List<string>();
foreach (object enumOption in enums)
{
enumDescriptions.Add(string.Format("{0} = {1}", (int)enumOption, Enum.GetName(enumOption.GetType(), enumOption)));
}
return string.Join(", ", enumDescriptions.ToArray());
}
}
This results in something like the following on your swagger-ui so at least you can "see what you're doing":