Привязка MVC к модели со свойством списка игнорирует другие свойства - PullRequest
30 голосов
/ 05 июля 2011

У меня есть базовая модель представления со свойством, которое представляет собой список сложных типов.При связывании мне кажется, что я застрял в получении списка значений ИЛИ других свойств модели в зависимости от опубликованных значений (т. Е. Расположения представления).

Модель представления:

public class MyViewModel
{
    public int Id { get; set; }
    public string Property1 { get; set; }
    public string Property2 { get; set; }

    public List<MyDataItem> Data { get; set; }
}

public class MyDataItem
{
    public int Id { get; set; }
    public int ParentId { get; set; }
    public string Name { get; set; }
    public string Value { get; set; }
}

Действия контроллера:

    public ActionResult MyForm()
    {
        MyViewModel model = new MyViewModel();

        model.Id = 1;
        model.Data = new List<MyDataItem>() 
        { 
            new MyDataItem{ Id = 1, ParentId = 1, Name = "MyListItem1", Value = "SomeValue"}
        }; 

        return View(model);
    }

    [HttpPost]
    public ActionResult MyForm(MyViewModel model)
    {
        //...

        return View(model);
    }

Вот базовый вид (без разметки списка)

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>My View Model</legend>

        @Html.HiddenFor(model => model.Id)

        <div class="editor-label">
            @Html.LabelFor(model => model.Property1)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Property1)
            @Html.ValidationMessageFor(model => model.Property1)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Property2)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Property2)
            @Html.ValidationMessageFor(model => model.Property2)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

При отправке обратно в контроллер я получаю 2 значения свойстви нулевое значение для свойства «Данные», как и ожидалось.

Without List Mark-up

Если я добавлю наценку для списка следующим образом (основываясь на информации в этом сообщении Скотта Хансельмана и сообщении Фила Хаака):

<div class="editor-field">
@for (int i = 0; i < Model.Data.Count(); i++)
{
    MyDataItem data = Model.Data[i];
    @Html.Hidden("model.Data[" + i + "].Id", data.Id)
    @Html.Hidden("model.Data[" + i + "].ParentId", data.ParentId)
    @Html.Hidden("model.Data[" + i + "].Name", data.Name)
    @Html.TextBox("model.Data[" + i + "].Value", data.Value)
}
</div>

Свойство «Данные» модели успешно связано, но остальные свойства имеют значение null.

With List Mark-up

Отправленные значения формы:

Id=1&Property1=test1&Property2=test2&model.Data%5B0%5D.Id=1&model.Data%5B0%5D.ParentId=1&model.Data%5B0%5D.Name=MyListItem1&model.Data%5B0%5D.Value=SomeValue

Есть ли способ заполнить оба набора свойств или я просто упускаю что-то очевидное?

РЕДАКТИРОВАТЬ:

Для тех из вас, кому любопытно.Исходя из ответа MartinHN , исходная сгенерированная наценка была:

<div class="editor-field">
    <input id="model_Data_0__Id" name="model.Data[0].Id" type="hidden" value="1" />
    <input id="model_Data_0__ParentId" name="model.Data[0].ParentId" type="hidden" value="1" />
    <input id="model_Data_0__Name" name="model.Data[0].Name" type="hidden" value="MyListItem1" />
    <input id="model_Data_0__Value" name="model.Data[0].Value" type="text" value="SomeValue" />        
</div>

Новая сгенерированная наценка:

<div class="editor-field">
    <input id="Data_0__Id" data-val="true" name="Data[0].Id" type="hidden" value="1" data-val-number="The field Id must be a number." data-val-required="The Id field is required." />
    <input id="Data_0__ParentId" name="Data[0].ParentId" type="hidden" value="1"  data-val="true" data-val-number="The field ParentId must be a number." data-val-required="The ParentId field is required." />
    <input id="Data_0__Name" name="Data[0].Name" type="hidden" value="MyListItem1" />
    <input id="Data_0__Value" name="Data[0].Value" type="text" value="SomeValue" />        
</div>

, что приводит кследующие опубликованные значения:

Id=1&Property1=test1&Property2=test2&Data%5B0%5D.Id=1&Data%5B0%5D.ParentId=1&Data%5B0%5D.Name=MyListItem1&Data%5B0%5D.Value=SomeValue

Обратите внимание, что «модель» отсутствует.в названии и опубликованных значениях ...

Ответы [ 3 ]

34 голосов
/ 05 июля 2011

Попробуйте изменить код сбора данных на этот, и пусть MVC позаботится о присвоении имен:

<div class="editor-field">
@for (int i = 0; i < Model.Data.Count(); i++)
{
    @Html.HiddenFor(m => m.Data[i].Id)
    @Html.HiddenFor(m => m.Data[i].ParentId)
    @Html.HiddenFor(m => m.Data[i].Name)
    @Html.TextBoxFor(m => m.Data[i].Value)
}
</div>
12 голосов
/ 13 сентября 2012

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

@model MyDataItem
@Html.HiddenFor(model => model.Id)
@Html.HiddenFor(model => model.ParentId)
@Html.HiddenFor(model => model.Name)
@Html.TextBoxFor(model => model.Value)

Создайте папку с именем «EditorTemplates» в папке «Shared» и сохраните вышеприведенное как «MyDataItem.cshtml».

Затем в вашем представлении просто вызовите следующее вместо foreach loop:

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

Чувствуется себя немного менее хакерским IMO:)

6 голосов
/ 03 ноября 2012

Только мои 2 цента, но кое-что стоит отметить в этой проблеме - элемент данных в модели представления должен быть определен как открытое свойство для работы привязки модели обратной передачи. У меня была проблема, очень похожая на описанную выше, но я использовал общедоступный элемент данных в моей модели представления. Генерируется тот же HTML, как показано выше, и все выглядит хорошо, но связыватель модели отбросил пустую коллекцию. Стоит посмотреть на ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...