Использование флажков для PostBack Enum с флагами
У меня есть свойство enum, и я пытаюсь установить его значение с помощью флажков. Перечисление помечается, и когда пользователь выбирает несколько опций, я ожидаю, что свойство объединит все выбранные флаги.
Я попытался добавить флажок для каждого значения перечисления и дал каждому флажку то же имя. Во время обратной передачи первый выбранный флаг извлекается, но не соединяется с другими флагами.
Могу ли я это как-то исправить, не имея отдельного свойства для каждого флага?
модель
public class HomeModel
{
public Fruit MyFruits { get; set; }
}
[Flags] public enum Fruit
{
Love = 1,
Joy = 2,
Peace = 4,
Patience = 8,
Kindness = 16,
Goodness = 32,
Faithfulness = 64,
Gentleness = 128,
SelfControl = 256
}
Посмотреть
@model EnumFlagTest.Models.HomeModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
@using (Html.BeginForm())
{
<h1>Fruits</h1>
<div><label>@EnumFlagTest.Models.Fruit.Love.ToString() <input type="checkbox" name="MyFruits" value="@((int) EnumFlagTest.Models.Fruit.Love)" @(Model.MyFruits.HasFlag(EnumFlagTest.Models.Fruit.Love) ? "checked" : String.Empty) /></label></div>
<div><label>@EnumFlagTest.Models.Fruit.Joy.ToString() <input type="checkbox" name="MyFruits" value="@((int) EnumFlagTest.Models.Fruit.Joy)" @(Model.MyFruits.HasFlag(EnumFlagTest.Models.Fruit.Joy) ? "checked" : String.Empty) /></label></div>
<div><label>@EnumFlagTest.Models.Fruit.Peace.ToString() <input type="checkbox" name="MyFruits" value="@((int) EnumFlagTest.Models.Fruit.Peace)" @(Model.MyFruits.HasFlag(EnumFlagTest.Models.Fruit.Peace) ? "checked" : String.Empty) /></label></div>
<div><label>@EnumFlagTest.Models.Fruit.Patience.ToString() <input type="checkbox" name="MyFruits" value="@((int) EnumFlagTest.Models.Fruit.Patience)" @(Model.MyFruits.HasFlag(EnumFlagTest.Models.Fruit.Patience) ? "checked" : String.Empty) /></label></div>
<div><label>@EnumFlagTest.Models.Fruit.Kindness.ToString() <input type="checkbox" name="MyFruits" value="@((int) EnumFlagTest.Models.Fruit.Kindness)" @(Model.MyFruits.HasFlag(EnumFlagTest.Models.Fruit.Kindness) ? "checked" : String.Empty) /></label></div>
<div><label>@EnumFlagTest.Models.Fruit.Goodness.ToString() <input type="checkbox" name="MyFruits" value="@((int) EnumFlagTest.Models.Fruit.Goodness)" @(Model.MyFruits.HasFlag(EnumFlagTest.Models.Fruit.Goodness) ? "checked" : String.Empty) /></label></div>
<div><label>@EnumFlagTest.Models.Fruit.Faithfulness.ToString() <input type="checkbox" name="MyFruits" value="@((int) EnumFlagTest.Models.Fruit.Faithfulness)" @(Model.MyFruits.HasFlag(EnumFlagTest.Models.Fruit.Faithfulness) ? "checked" : String.Empty) /></label></div>
<div><label>@EnumFlagTest.Models.Fruit.Gentleness.ToString() <input type="checkbox" name="MyFruits" value="@((int) EnumFlagTest.Models.Fruit.Gentleness)" @(Model.MyFruits.HasFlag(EnumFlagTest.Models.Fruit.Gentleness) ? "checked" : String.Empty) /></label></div>
<div><label>@EnumFlagTest.Models.Fruit.SelfControl.ToString() <input type="checkbox" name="MyFruits" value="@((int) EnumFlagTest.Models.Fruit.SelfControl)" @(Model.MyFruits.HasFlag(EnumFlagTest.Models.Fruit.SelfControl) ? "checked" : String.Empty) /></label></div>
<input type="submit" value="GO" />
}
</div>
</body>
</html>
контроллер
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index()
{
HomeModel model = new HomeModel();
model.MyFruits = Fruit.Love | Fruit.Joy | Fruit.Peace | Fruit.Patience;
return View(model);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(HomeModel returnData)
{
return View(returnData);
}
1 ответ
Если вы проверяете тело сообщения POST, данные отправляются, они просто не подобраны должным образом. Это потому, что MVC плохо обрабатывает перечисления флагов. Кто-то, кто ответил на подобный вопрос, описывает это:
В целом, я избегаю использования перечислений при разработке моих моделей представлений, потому что они не работают с помощниками ASP.NET MVC и из связующего устройства из коробки. Они прекрасно подходят для моделей вашего домена, но для моделей просмотра вы можете использовать другие типы.
Там человек, отвечающий на вопрос, также дает полный ответ о том, как в любом случае связать перечисление флагов. Что вам в основном нужно сделать, так это создать свой собственный механизм связывания моделей, который может обрабатывать перечисление флагов. В другом посте под названием Binder Model Enumeration Model Binder ASP.Net MVC я нашел пример, и я скопирую соответствующий код.
Добавить класс с именем CustomModelBinder
следующее:
public class CustomModelBinder : DefaultModelBinder
{
protected override object GetPropertyValue(
ControllerContext controllerContext,
ModelBindingContext bindingContext,
PropertyDescriptor propertyDescriptor,
IModelBinder propertyBinder)
{
var propertyType = propertyDescriptor.PropertyType;
// Check if the property type is an enum with the flag attribute
if (propertyType.IsEnum && propertyType.GetCustomAttributes(true).Any())
{
var providerValue = bindingContext.ValueProvider
.GetValue(bindingContext.ModelName);
if (providerValue != null)
{
var value = providerValue.RawValue;
if (value != null)
{
// In case it is a checkbox list/dropdownlist/radio
// button list
if (value is string[])
{
// Create flag value from posted values
var flagValue = ((string[])value)
.Aggregate(0, (acc, i)
=> acc | (int)Enum.Parse(propertyType, i));
return Enum.ToObject(propertyType, flagValue);
}
// In case it is a single value
if (value.GetType().IsEnum)
{
return Enum.ToObject(propertyType, value);
}
}
}
}
return base.GetPropertyValue(controllerContext,
bindingContext,
propertyDescriptor,
propertyBinder);
}
}
Затем в Global.asax.cs Application_Start
Метод регистрации пользовательского связующего модели выглядит следующим образом:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
// Register custom flag enum model binder
ModelBinders.Binders.DefaultBinder = new CustomModelBinder();
}
Это должно работать.
Источник: http://itq.nl/asp-net-mvc-flag-enumeration-model-binder/