Подтвердить что ты не робот

MVC3 - Viewmodel со списком сложных типов

Извините, если это было задано раньше; есть миллион способов выразить это, поэтому поиск ответа оказался трудным.

У меня есть viewmodel со следующими свойствами:

public class AssignSoftwareLicenseViewModel
{
    public int LicenseId { get; set; }
    public ICollection<SelectableDeviceViewModel> Devices { get; set; }
}

Упрощенная версия SelectableDeviceViewModel будет следующей:

public class SelectableDeviceViewModel
{
    public int DeviceInstanceId { get; set; }
    public bool IsSelected { get; set; }
    public string Name { get; set; }
}

В моем представлении я пытаюсь отобразить список редактируемых флажков для свойства Devices, внутри формы ввода. В настоящее время мой вид выглядит следующим образом:

@using (Html.BeginForm())
{
    @Html.HiddenFor(x => Model.LicenseId)
    <table>
        <tr>
            <th>Name</th>
            <th></th>
        </tr>
        @foreach (SelectableDeviceViewModel device in Model.Devices)
        {
            @Html.HiddenFor(x => device.DeviceInstanceId)
            <tr>
                <td>@Html.CheckBoxFor(x => device.IsSelected)</td>
                <td>@device.Name</td>
            </tr>
        }
    </table>

    <input type="submit" value="Assign" />
}

Проблема заключается в том, что когда модель возвращается к контроллеру, Устройства имеют нулевое значение.

Мое предположение заключается в том, что это происходит, потому что, хотя я редактирую его содержимое, свойство Devices никогда явно не включено в форму. Я попытался включить его с помощью HiddenFor, но это привело к тому, что модель имела пустой список вместо null.

Любая идея, что я делаю неправильно здесь?

4b9b3361

Ответ 1

Мое предположение заключается в том, что это происходит, потому что, хотя я редактируя его содержимое, свойство Devices никогда явно не указано включены в форму.

Нет, ваше предположение неверно. Причина, по которой это не связано должным образом, заключается в том, что ваши поля ввода не имеют правильных имен. Например, они называются name="IsSelected" вместо name="Devices[0].IsSelected". Взгляните на правильный формат проводов, который необходимо использовать для привязки к коллекциям: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Но почему это происходит?

Это происходит из-за цикла foreach, который вы использовали в своем представлении. Вы использовали x => device.IsSelected в качестве лямбда-выражения для этого флажка, но это вообще не учитывает свойство Devices (как вы можете видеть, глядя на сгенерированный исходный код вашей веб-страницы).

Так что мне делать?

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

@Html.EditorFor(x => x.Devices)

и теперь определите настраиваемый шаблон редактора, который будет автоматически отображаться ASP.NET MVC для каждого элемента коллекции Devices. Предупреждение: расположение и имя этого шаблона очень важны, поскольку это работает по соглашению: ~/Views/Shared/EditorTemplates/SelectableDeviceViewModel.cshtml:

@model SelectableDeviceViewModel
@Html.HiddenFor(x => x.DeviceInstanceId)
<tr>
    <td>@Html.CheckBoxFor(x => x.IsSelected)</td>
    <td>@Html.DisplayFor(x => x.Name)</td>
</tr>

Другой подход (который я не рекомендую) заключается в изменении текущего ICollection в вашей модели представления на индексированную коллекцию (например, IList<T> или массив T[]):

public class AssignSoftwareLicenseViewModel
{
    public int LicenseId { get; set; }
    public IList<SelectableDeviceViewModel> Devices { get; set; }
}

а затем вместо foreach используйте цикл for:

@for (var i = 0; i < Model.Devices.Count; i++)
{
    @Html.HiddenFor(x => x.Devices[i].DeviceInstanceId)
    <tr>
        <td>@Html.CheckBoxFor(x => x.Devices[i].IsSelected)</td>
        <td>@Html.DisplayFor(x => x.Devices[i].Name</td>
    </tr>
}

Ответ 2

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

Однако есть ли у кого-нибудь проблемы с проверкой на сложных видовых моделях (вложенные шаблоны EditorFor)? Я использую Kendo Validator и запускаю всевозможные ошибки jquery.