Каков правильный подход к редактированию нескольких элементов в MVC 3?

У меня есть продукт базового класса (свойства: int ProductID, строковое имя, десятичная цена) и некоторые типы экземпляров, основанные на продукте, например. HardDisk, которые имеют дополнительные свойства.

Я экспериментирую с правками в одном представлении, которое имеет модель, основанную на списке продуктов:

@model List<Product>

Это представление имеет один оператор редактора:

@Html.EditorForModel(Model)

Я создал шаблон редактора для класса Product, который представляет собой единую форму Ajax, позволяющую пользователю редактировать имя для каждого продукта:

@model Product
@{
    // set unique IDs for result divs
    var resultDiv = "result" + Model.ProductID.ToString();
}
@using (Ajax.BeginForm("Update", new AjaxOptions
{
    HttpMethod = "POST",
    LoadingElementId = "working",
    UpdateTargetId = @resultDiv,
    InsertionMode = InsertionMode.Replace
}
))
{
    <div style="padding: 4px; margin-bottom: 4px; border: 1px solid gray; background-color: #eee;">
        @Html.HiddenFor(m => m.ProductID)
        @Html.DisplayFor(m => m.Name)
        @Html.LabelFor(m => m.Name)
        @Html.EditorFor(m => m.Name)
        <input type="submit" value="Save" />
        <span id="@resultDiv">...</span>
    </div>

}

Это прекрасно работает для первой строки (с идентификатором [0].Name) для отправки данных с одной записью. Однако редактирование второй или третьей строки приводит к нулевым данным в сообщении.


person Quango    schedule 21.02.2012    source источник


Ответы (3)



Выяснил причину и решение здесь - ссылку «Привязка модели к списку» было полезно прочитать.

Проблема здесь в том, что связыватель модели предполагает, что индекс будет начинаться с нуля и продолжаться. Сгенерированные имена для каждого элемента следуют этому шаблону:

[0].ProductID, [0].Name
[1].ProductID, [1].Name
[2].ProductID, [2].Name

Однако, поскольку я использовал одну форму AJAX для отправки каждой записи, связыватель модели мог создать действительный список из индекса только в том случае, если я редактировал первый элемент ( [0] ).

Если бы я редактировал второй элемент, сообщение формы имело бы только значения для [1].ProductId и [1].Name — так что это не был индекс с отсчетом от нуля — поэтому связующему не удалось воссоздать данные о продукте — отсюда нулевое значение.

Мое решение состояло в том, чтобы относиться к POST как к тому, чем он является на самом деле — единственное редактирование одного объекта. Для этого мне нужно было изменить атрибут «имя» в каждом элементе управления только на «ProductID» и «Name», а затем изменить метод Update, который обрабатывает POST, чтобы ожидать один тип продукта.

Тогда это работало отлично.

person Quango    schedule 21.02.2012

нам нужно предоставить индекс для каждого элемента для привязки сложных объектов.

<% for (int i = 0; i < Product.count; i++) { %>

 <%: Html.HiddenFor(m => m[i].ProductID) %>

  <%: Html.TextBoxFor(m => m[i].Name) %>

<%: Html.TextBoxFor(m => m[i].Price) %> 

<% } %>

Если вы используете шаблонные помощники, используйте шаблон, как показано ниже, на главной странице просмотра.

<% for (int i = 0; i < Product.count; i++) { %>

  <%: Html.EditorFor(m => m[i]) %>

<% } %>

В Product.ascx (частичная страница или помощник по шаблону)

 <%@ Control Inherits="ViewUserControl<Product>" %>

 <%: Html.HiddenFor(m => m[i].ProductID) %>

      <%: Html.TextBoxFor(m => m[i].Name) %>

    <%: Html.TextBoxFor(m => m[i].Price) %>
person MikMark    schedule 21.02.2012
comment
Спасибо за комментарий - сгенерированные идентификаторы создают индекс, поскольку идентификаторы [0].Name, [1].Name, [2].Name и т. д. Однако теперь я нашел решение - person Quango; 21.02.2012