MVC3 ModelBinding для коллекции, отправленной обратно с пробелами в индексе

У меня есть коллекция объектов в моей модели, которые я отображаю в представлении с помощью функции EditFor, и у меня есть EditorTemplate, который отвечает за фактическую визуализацию каждого объекта.

@Html.EditorFor(model => model.MyObjects)

Это хорошо работает некоторое время, и когда вы проверяете html, мои текстовые поля имеют префикс свойства модели, за которым следует индекс коллекции, из которой они взяты.

<input class="text-box single-line" id="MyObjects_2__SomeProperty" 
name="MyObjects[2].SomeProperty" type="Text" value="" />

Однако недавно я начал использовать свойства ShowForEdit и ShowForDisplay в метаданных модели для коллекции, и в первой строке моего шаблона редактора, если ShowForEdit не соответствует действительности, я просто пропускаю его.

@if (!ViewData.ModelMetadata.ShowForEdit)
{
    return;
}

Но поскольку все они проиндексированы в html, когда я пытаюсь сохранить эту коллекцию обратно в модель представления с помощью обратной передачи, она терпит неудачу из-за зависимости от номеров индексации. Каждый элемент в коллекции после отсутствующего индекса отсутствует в моей модели представления, когда я проверяю его значение.

В этом случае на самом деле это мой первый элемент в коллекции, который я пропускаю, так как я не хочу, чтобы он был виден в режиме редактирования, но из-за этого, когда я выполняю обратную передачу, первый индекс в html равен 1 (вместо 0 как обычно), но это проблема, когда вы пытаетесь сохранить изменения. Это также проблема при изменении DOM с помощью javascript.

Кто-нибудь еще сталкивался с проблемой, связанной со способностью связывателя модели по умолчанию читать данные, отправленные обратно, когда один или несколько индексов в представленной html коллекции отсутствуют?

Существуют ли связующие модели, которые решают эту проблему?


person Nick Albrecht    schedule 27.07.2011    source источник
comment
Для asp.net-mvc-3 я бы рекомендовал посмотреть Непоследовательные индексы MVC3 и DefaultModelBinder. По сути, просто добавьте скрытое поле (для каждого элемента коллекции) со специальным именем MyCollection.Index с индексом в качестве значения.   -  person Joel Purra    schedule 03.04.2012


Ответы (2)


Есть несколько очень хороших сообщений в блогах, которые позволяют вам привязать модель к списку без необходимости предоставлять непрерывный индекс, основанный на нуле. Пожалуйста, взгляните на http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
http://zahidadeel.blogspot.com/2011/05/master-detail-form-in-aspnet-mvc-3-ii.html
Кроме того, если вас интересует шаблон MVVM и нокаут js, вы можете проверить эту замечательную работу на стив сандерсон
length list mvc style" в гугле и выдаст десяток полезных ссылок

person Muhammad Adeel Zahid    schedule 28.07.2011
comment
Я отсортировал несколько предоставленных вами ссылок, но большинство из них отвечают на несколько небольших образцов кода, а остальные включены в более крупную загрузку проекта, которую вам нужно просмотреть, чтобы найти соответствующие фрагменты, что лично меня очень раздражает. . Однако я изменил предложенные вами условия поиска и нашел это сообщение, которое помогло. ссылка По иронии судьбы, это очень похоже на то, как я сделал это в MVC2, но затем обнаружил поддержку автоматически сгенерированных индексов и в итоге использовал ее вместо этого. - person Nick Albrecht; 28.07.2011

Недавно столкнулся с этой проблемой и решил ее, преобразовав список в словарь‹string, model› с GUID в качестве ключа.

@foreach (var index in Model.EmailAddresses.Keys)
{
    <label asp-for="@Model.EmailAddresses[index].Email">Email</label>
    <input asp-for="@Model.EmailAddresses[index].Email" type="text" />
}

Это позволило избежать включения скрытых входных данных, которые сопоставляются со значением индекса.

person nelowe    schedule 14.10.2020
comment
Это может не работать со старыми версиями asp.net-mvc, которые я использовал в то время, когда впервые столкнулся с этой проблемой. Вполне возможно, что более новые версии (или даже asp.net-core) упростили это, но я не пытался удалить свойство Index, чтобы увидеть. Также стоит отметить, что использование вспомогательного метода, описанного в предложенных ссылках, имеет дополнительное преимущество каскадного обхода модели представления по цепочке, чтобы EditorTemplates, DisplayTemplates и т. д. работали с ним. Где, поскольку вы явно должны были указать index. - person Nick Albrecht; 15.10.2020