我正在使用 FluentValidation,并且我只想从 Fluent 验证器接收我的自定义错误。这就是为什么我的请求类中的所有属性都是字符串。但是,我还希望有更好的枚举类型文档。
这是我的样品请求:
public class AddNewPaymentRequest
{
[EnumDataType(typeof(PaymentStatus))]
public string PaymentStatus { get; set; }
public string Id { get; set; }
}
和示例枚举:
public enum PaymentStatus
{
Unknown,
New,
Pending,
Completed
}
和控制器:
[HttpPost]
public async Task<ActionResult> PostAsync([FromBody] AddNewPaymentRequest request)
{
...
}
我想让这个 EnumDataType 作为 Swagger 的信息来显示枚举描述,而不是字符串描述。我希望 Swagger 将此字符串视为枚举。
是否有可能以这种方式配置 Swashbuckle?
我想我们正在谈论 .NET Core
如果你可以的话,可以将其明确定义为枚举而不是字符串
public class AddNewPaymentRequest
{
//[EnumDataType(typeof(PaymentStatus))]
//public string PaymentStatus { get; set; }
public PaymentStatus PaymentStatus { get; set; }
public string Id { get; set; }
}
然后您可以定义 SwaggerGen 如何处理枚举
services.AddSwaggerGen(c => {c.DescribeAllEnumsAsStrings(); } );
如果您在 api 接收/发送数据时遇到序列化/反序列化枚举(由 Newtonsoft.Json 提供)的问题,您可以对转换采取更多控制器(如有必要)
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
public enum PaymentStatus
{
[EnumMember(Value = "Unknwon")]
Unknown,
[EnumMember(Value = "New")]
New,
[EnumMember(Value = "Pending")]
Pending,
[EnumMember(Value = "Completed")]
Completed,
[EnumMember(Value = "something_different_with_underline")]
SomethingDifferentWithUnderline
}
请注意,这些枚举的 ToString() 可能会导致不同的字符串(带/不带)下划线
Swaggers 仅支持
RequiredAttribute
、ObsoleteAttribute
和 MetaData
(用于外部类)。
所以除了写这样的东西之外,没有办法描述可接受的价值观:
/// <summary> Allowed values are....
这些答案都有效地表明“你不能这样做,这里还有其他选择。”好吧,你可以做到,具体方法如下。
创建一个名为
OpenApiEnumAttribute
的属性,如下所示:
/// <summary>
/// Used in conjunction with OpenApiEnumSchemaFilter to apply the enum property
/// to an OpenAPI schema.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class OpenApiEnumAttribute : Attribute
{
public OpenApiEnumAttribute(params string[] enumOptions)
{
EnumOptions = enumOptions;
}
public OpenApiEnumAttribute(Type enoom)
{
if (!enoom.IsEnum)
{
throw new ArgumentException("Type not an enum", nameof(enoom));
}
EnumOptions = Enum.GetNames(enoom);
}
/// <summary>
/// Options for values that the property can have
/// </summary>
public string[] EnumOptions { get; }
}
然后还创建一个架构过滤器,如下所示:
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
/// <summary>
/// Applies the enum property to an OpenAPI schema. Most useful to constrain
/// strings to be a specific value.
/// </summary>
public class OpenApiEnumSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (context.MemberInfo == null)
{
return;
}
var enumAnnotation = context.MemberInfo.GetCustomAttributes(typeof(OpenApiEnumAttribute), false)
.Cast<OpenApiEnumAttribute>()
.FirstOrDefault();
if (enumAnnotation == null) return;
schema.Enum = enumAnnotation.EnumOptions.Select(option => new OpenApiString(option))
.Cast<IOpenApiAny>().ToList();
}
}
最后在你的 Startup.cs 中(或者你调用的任何地方
AddSwaggerGen
:
services.AddSwaggerGen(config => { config.SchemaFilter<OpenApiEnumSchemaFilter>(); } );
根据您的示例,您现在可以像这样使用它:
public class AddNewPaymentRequest
{
[OpenApiEnum(typeof(PaymentStatus))]
public string PaymentStatus { get; set; }
public string Id { get; set; }
}