Я думаю, что этот вопрос можно разбить на 2 части,
- Пользовательская строка для преобразования в Enum с использованием
EnumMemberAttribute
- Указание MVC использовать это пользовательское преобразование для привязки входов модели.
Я собираюсь ответить на 2 часть, и, надеюсь, первая часть должна быть относительно простой для реализации / исследования. Я включил ссылку на вопрос непосредственно о первой части.
Указание MVC использовать пользовательское преобразование перечисления для привязки входов модели.
Получение значений от клиента всегда осуществляется посредством привязки модели, тогда как сериализация json в основном связана с форматированием данных ответа в виде json для вывода. Таким образом, ваше решение должно рассмотреть возможность связывания модели десериализации перечислений, которую вы хотите использовать. (Реализация по умолчанию преобразования строк enum <=> не рассматривает атрибуты).
Я попробовал следующее пользовательское связующее для моего enum, и оно работало хорошо. FooType
мое перечисление:
public enum FooType
{
[Description("test")]
TestFoo,
[Description("another")]
AnotherFooType
}
Я пропустил атрибут [EnumMember]
и выбрал атрибут [Description]
только потому, что хотел использовать Утилита Enum от Humanizer , но вы можете реализовать свой собственный способ получения значений перечисления из EnumMember
атрибут и просто заменить мой вызов DeHumanizeTo<FooType>()
, пример можно найти на этот вопрос .
public class FooTypeBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext) => Task.Run(() => this.BindModel(bindingContext));
private void BindModel(ModelBindingContext bindingContext)
{
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult.Length == 0)
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "No value was provided for enum");
return;
}
var stringValue = valueProviderResult.FirstValue;
try
{
bindingContext.Model = this.FromString(stringValue);
}
catch (NoMatchFoundException ex)
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, ex.Message);
}
}
private FooType FromString(string input)
{
//Here you should implement your custom way of checking the [EnumMember] attribute, and convert input into your enum.
if (Enum.TryParse(typeof(FooType), input, true, out object value))
{
return (FooType)value;
}
else return input.DehumanizeTo<FooType>();
}
}
В моем контроллере я тогда говорю MVC использовать это связующее для привязки моих параметров следующим образом:
[HttpGet("{fooType}")]
public IActionResult GetFooItems([ModelBinder(BinderType = typeof(FooTypeBinder))] FooType fooType)
{
// Do your thing, your enum fooType is bound correctly
return this.Ok(fooType);
}
Надеюсь, это поможет.