以往在 controller 裡使用了 enum 的參數,但在 swagger 中顯示的都很悲劇,導致使用端會不知道怎麼使用這個參數,或是這些值分別是代表什麼
以下面這個例子來看,Color 1, 3, 5 分別是代表什麼?
public enum Color
{
R = 1,
G = 3,
B = 5
};
public class ColorModifyReq
{
public Color color { set; get; }
public int userId { set; get; }
}
[ApiController]
[Route("api/v1/[controller]")]
public class UserController : ControllerBase
{
/// <summary>
/// 替某個使用者設定顏色碼
/// </summary>
/// <param name="color"></param>
/// <param name="id"></param>
/// <returns></returns>
[HttpPut("color")]
[SwaggerRequestExample(typeof(ColorModifyReq), typeof(ColorModifyReqSample))]
public IActionResult Color(ColorModifyReq req)
{
return Ok();
}
}
public class ColorModifyReqSample : IExamplesProvider<ColorModifyReq>
{
public ColorModifyReq GetExamples()
{
return new ColorModifyReq
{
color = Color.R,
userId =123
};
}
}
swagger 是有方式可以解決這個問題的
需要先加上 filter 主要用來處理 enum 型別的問題
public class EnumSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (context.Type.IsEnum)
{
schema.Enum.Clear();
Enum.GetNames(context.Type)
.Select(e => new
{
DisplayString = e,
EnumValue = (int)Enum.Parse(context.Type, e)
})
.ToList()
.ForEach(name => schema.Enum.Add(new OpenApiString($"[{name.EnumValue}]:{name.DisplayString}")));
}
}
}
最後在啟動時把這個 filter 掛上來就好了
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "demo", Version = "v1" });
c.ExampleFilters();
c.SchemaFilter<EnumSchemaFilter>();
// Set the comments path for the Swagger JSON and UI.
List<string> xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml", SearchOption.TopDirectoryOnly).ToList();
xmlFiles.ForEach(xmlFile => c.IncludeXmlComments(xmlFile));
c.CustomSchemaIds(x => x.FullName);
});
接著來看看結果
收到資料也是正常的
參考資料: https://thomasdewulf.dev/posts/enums-net6-openapi/