Еще раз я столкнулся с ситуацией "Это не должно быть? *! # Hard".
Проблема: я хочу использовать форму в MVC для создания объекта. Одним из элементов объекта является набор ограниченных вариантов - идеальный кандидат для выпадающего списка.
Но если я использую SelectList в моей модели и раскрывающийся список в моем представлении, а затем пытаюсь опубликовать модель обратно в мой метод Create, я получаю ошибку «Исключение отсутствующего метода: нет конструктора без параметров для этого объекта» ». Изучая исходный код MVC, выясняется, что для привязки к модели Binder должен сначала иметь возможность его создать, и он не может создать SelectList, поскольку для него нет конструктора по умолчанию.
Вот упрощенный код:
Для модели:
public class DemoCreateViewModel
{
public SelectList Choice { get; set; }
}
Для контроллера:
//
// GET: /Demo/Create
public ActionResult Create()
{
DemoCreateViewModel data = new DemoCreateViewModel();
data.Choice = new SelectList(new string[] { "Choice1", "Choice2", "Choice3" });
ViewData.Model = data;
return View();
}
//
// POST: /Demo/Create
[HttpPost]
public ActionResult Create(DemoCreateViewModel form)
{
try
{
// TODO: Add insert logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
А для просмотра:
<fieldset>
<legend>Fields</legend>
<%= Html.LabelFor(model => model.Choice) %>
<%= Html.DropDownListFor(model => model.Choice, Model.Choice) %>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
Теперь я знаю, что Я МОГУ СДЕЛАТЬ эту работу, отбросив 10 ярдов и сделав выбор: обойти привязку модели и вернуться к FormCollection, а также проверить и связать все поля самостоятельно, но должен быть более простой способ. Я имею в виду, что это примерно такое же простое требование, как и оно. Есть ли способ заставить это работать в архитектуре MVC ModelBinding? Если так, то, что это? А если нет, то почему?
Редактировать: Ну, у меня на лице яйцо, но, возможно, это поможет кому-то еще. Я провел еще несколько экспериментов и нашел простое решение, которое, кажется, работает.
Укажите простое значение (строка или целое число, в зависимости от типа значения в списке выбора) и назовите его как элемент модели, к которому вы привязываете. Затем укажите второй элемент в качестве списка выбора и назовите его как-нибудь еще. Итак, моя модель стала:
public class DemoCreateViewModel
{
public string Choice { get; set; }
public SelectList Choices { get; set; }
}
И тогда оператор DropDownListFor в представлении становится:
<%= Html.DropDownListFor(model => model.Choice, Model.Choices) %>
Когда я это делаю, кнопка отправки правильно связывает сделанный в форме выбор со строкой Выбор и отправляет модель обратно во второй метод Create.