Привязка словаря, содержащего список в MVC4
У меня возникают проблемы при публикации формы, содержащей словарь, который содержит int в качестве ключа и список объектов в качестве значения.
Первоначально это был просто список объектов, и он работал нормально, а тип был:
List<MyObject> Fields
рабочая разметка была
Fields_{0}__Property1
где {0} - индекс объекта. Чтобы получить возможность отправить обратно список объектов, я визуализировал объект со скрытыми полями, например:
@Html.HiddenFor(m => m.Property1, new { Name = string.Format("Fields[{0}].Property1", Model.Index), @id = string.Format("Fields_{0}__Property1", Model.Index) })
Это сработало хорошо. Однако теперь у нас есть словарь вместо списка, и этот список находится внутри словаря.
Теперь тип:
Dictionary<int, List<MyObject>>.
Я протестировал ожидаемый формат при рендеринге словаря с помощью Html.HiddenFor, и поэтому я добавил скрытые поля с требуемым форматом, который сейчас:
@Html.HiddenFor(m => m.Property1, new { Name = string.Format("Fields[{0}][{1}].Property1", Model.Index, Model.Position), @id = string.Format("Fields_{0}__{1}__Property1", Model.Index, Model.Position) })
теперь идентификатор поля
Fields_{0}__{1}__Property1
где {0} - это ключ словаря, а {1} - это индекс объекта в списке.
Однако на обратной передаче я теперь получаю
[InvalidCastException: Specified cast is not valid.]
System.Web.Mvc.CollectionHelpers.ReplaceDictionaryImpl(IDictionary`2 dictionary, IEnumerable`1 newContents) +131
Я предполагаю, что MVC достаточно умен, чтобы визуализировать поля этого сложного объекта в представлении, но не настолько умен, чтобы собирать их обратно в модель представления, когда мы отправляем назад.
Я нашел другого парня, у которого здесь была похожая проблема, и он решил ее, не используя словарь, а создавая сложный объект. Мне интересно, однако, есть ли более быстрый способ, который не потребует от меня переписать всю систему.
Есть идеи?
Обновить
Я решил это, взяв исходный код DefaultModelBinder и настроив его. Я нашел источник здесь. Я не создал свой собственный Binder, потому что я хочу, чтобы все расширенные функциональные возможности и правила проверки применялись ко всем другим элементам. Как только я получил компиляцию и работу DefaultModelBinder, я нашел часть, в которой словарь не смог преобразовать сложные элементы, и написал собственный метод обновления словаря, который решил проблему.
1 ответ
Вы всегда можете создать пользовательский связыватель модели, чтобы привязать объекты из значений запроса именно так, как вы хотите. Просто создайте класс, который реализует System.Web.Mvc.IModelBinder
интерфейс и реализовать BindModel()
метод.