Я использую DescriptionAttribute
в Enums для предоставления описания, которое включает пробелы. Я создал несколько методов расширения, которые будут возвращать строковое описание перечисления и / или возвращать значение перечисления из строкового описания.
Теперь я хочу, чтобы мой WebAPI использовал эти методы расширения для обработки преобразования типов Enum вместо TypeConverter по умолчанию, чтобы я мог передать значение типа "Car Wash"
и сопоставить его с Enum.
Есть ли способ переопределить строку по умолчанию для Enum TypeConverter?
Окружающая среда
.NetCore 2.x
Обновление - мой текущий код
Мой текущий код прекрасно работает, когда контроллер сериализует объект в JSON для отправки клиенту. Учитывая приведенное ниже значение Enum
, значение enum 0 приведет к тому, что клиент получит строку «Mental Health» - идеально. Тем не менее, теперь, когда клиент отправляет «Mental Health» обратно на сервер - мне нужно преобразовать обратно в AgencyTpes.MentalHealth
. В данный момент механизм привязки выдает ошибку.
//Example Enum
public enum AgencyTypes {
[Description("Mental Health")]
MentalHealth,
Corrections,
[Description("Drug & Alcohol")]
DrugAndAlcohol,
Probation
}
Мои расширения Enum, работающие с DescriptionAttribute
public static class EnumExtensions
{
public static string ToDisplayString(this Enum values)
{
var attribute = value.GetType().GetMember(value.ToString())
.FirstOrDefault()?.GetCustomAttribute<DescriptionAttribute>();
return attribute ?.Description ?? value.ToString();
}
public static object GetValueFromDescription(string description, Type enumType)
{
return Convert.ChangeType(LookupDescription(description,enumType),enumType);
}
public static T GetValueFromDescription<T>(string description) where T: struct
{
return (T)LookupDescription(description, typeof(T));
}
private static object LookupDescription(string description, Type enumType)
{
if(!enumType.IsEnum)
throw new ArgumentException("Type provided must be an Enum", enumType.Name);
foreach(var field in enumType.GetFields())
{
var attribute = Attribute.GetCustomAttribute(field, tyepof(DescriptionAttribute)) as DescriptionAttribute;
if((attribute != null && attribute.Description == description)
|| field.Name == description)
{
return field.GetValue(null);
}
}
throw new ArgumentException($"Requested value for '{description}' in enum {enumType.Name} was not found", nameof(description));
}
}
Переопределение JSON для включения контроллеров для преобразования enum в строку
//Startup.cs
services.AddMvc().SetCompatibilityVersion(Compatibility.Version_2_2)
.AddJsonOptions(options =>
{
options.SerializerSettings.Converters.Add(new StringAnnotationEnumConverter());
});
public class StringAnnotationEnumConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var token = JToken.Load(reader);
var value = token.ToString();
if(reader.TokenType == JsonToken.String)
return EnumExtensions.GetValueFromDescription(value, objectType);
else
return base.ReadJson(reader, objectType, existingValue, serializer);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if(value == null)
{
writer.WriteNull();
return;
}
Enum e = (Enum)value;
string enumName = e.ToDisplayString();
if(string.IsNullOrWhiteSpace(enumName))
throw new JsonSerializationException(String.Format("Integer value {0} is not allowed.",e.ToString("D")));
writer.WriteValue(enumName);
}
}
Обновление 2 - WebAPI
Вот пример кода объекта Controller & Domain
public class Agency
{
public int Id {get; set;}
public string Name {get; set;}
public AgencyTypes AgencyType {get; set;}
...
}
[ApiController]
public class AgencyController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Agency([FromForm] Agency agency)
{
...
}
}