我正试图让枚举在描述中(或任何其他属性)以友好的方式显示友好名称。还尝试解析控制器操作中在body / querystring上设置的友好名称,而不尝试尝试400 BadRequest或任何种类的验证错误。我还注意到,我拥有的自定义通用JsonConverter也无法正常工作。根本不会调用ReadJson()方法。我该如何工作?救命!
[JsonConverter(typeof(JsonEnumConverter<SortDirectionType>))]
public enum SortDirectionType
{
[Description("asc")]
ASCENDING,
[Description("desc")]
DESCENDING
}
我试图获取swagger-ui以将asc&desc显示为下拉列表中的值,而不是ASCENDING&DESCENDING。这意味着我不能使用c.DescribeAllEnumsAsStrings()
。如果我不使用它,则下拉列表将显示0,1,因为它应该代表枚举成员值。现在,我可以使用[EnumMember(Value="asc"]
属性而不是[Description("asc")]
属性。但是,随后发生了两件事:
1. swagger-ui都会引发客户端验证,并用红色线条突出显示该字段
2.或者,如果我尝试在swagger之外调用端点,则会返回400错误。
3.我可以在操作[FromBody]
参数中成功使用0,1或ASCENDENING,DESCENDING值。但是,这不是预期的。我将要接收asc,desc,并希望能够在主体模型上成功解析它并将其映射到enum属性。在另一方面,当json呈现时,它应该呈现友好名称。
附加代码:
public class JsonEnumConverter<T> : JsonConverter where T : struct, IComparable, IConvertible, IFormattable
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(T);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var type = typeof(T);
if (!type.IsEnum) throw new InvalidOperationException();
var enumDescription = (string)reader.Value;
return enumDescription.GetEnumValueFromDescription<T>();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var type = typeof(T);
if (!type.IsEnum) throw new InvalidOperationException();
if (value != null)
{
if (value is Enum sourceEnum)
{
writer.WriteValue(sourceEnum.GetDescriptionFromEnumValue());
}
}
}
}
public static class EnumExtensions
{
public static string GetDescriptionFromEnumValue(this Enum @enum)
{
FieldInfo fi = @enum.GetType().GetField(@enum.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute),
false);
if (attributes != null &&
attributes.Length > 0)
return attributes[0].Description;
else
return @enum.ToString();
}
public static T GetEnumValueFromDescription<T>(this string description)
{
var type = typeof(T);
if (!type.IsEnum)
throw new InvalidOperationException();
foreach (var field in type.GetFields())
{
if (Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) is DescriptionAttribute attribute)
{
if (attribute.Description == description)
return (T)field.GetValue(null);
}
else
{
if (field.Name == description)
return (T)field.GetValue(null);
}
}
throw new ArgumentException($"No matching value for enum {nameof(T)} found from {description}.",$"{nameof(description)}"); // or return default(T);
}
}
答案 0 :(得分:0)
答案 1 :(得分:0)
我想出了一个办法。不一定是适合您的解决方案,但是,如果您可以使它起作用,那么我很高兴可以提供帮助。
最终将枚举格式更改为字符串,而不是默认下拉列表。这样,我可以将asc / desc值发送到api。 Swagger接受了这些值,并且没有抛出验证错误。我在.net核心api上编写的转换器也能够很好地转换它们。
c.MapType<SortDirectionType>(() => new Schema { Type = "string", Format = "string" });
除此之外,您可能还希望禁用自动启动的asp.net core 2.2验证的默认行为。不确定为什么他们选择将其设置为默认行为。
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});