Привязка словаря, содержащего список в 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() метод.

Другие вопросы по тегам