ASP.Net MVC - модель с коллекцией, не пополняемая при обратной передаче - PullRequest
10 голосов
/ 20 мая 2009

У меня есть приложение ASP.Net MVC с моделью, состоящей из нескольких уровней и содержащей коллекцию.

Я считаю, что представление для создания объектов настроено правильно, но оно просто не заполняет коллекцию в модели, когда я отправляю форму на сервер.

У меня есть часть данных, которая находится в иерархии классов таким образом:

person.PersonDetails.ContactInformation[0].Data;

Эта структура класса создана LinqToSQL, а ContactInformation имеет тип EntitySet<ContactData>. Для создания представления я передаю следующее:

return View(person);

и в представлении у меня есть форма, которая содержит одно текстовое поле с именем, связанным с вышеупомянутым полем:

<%= Html.TextBox("person.PersonDetails.ContactInformation[0].Data")%>

Метод post в моем контроллере будет следующим:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create (Person person)
{
  //Do stuff to validate and add to the database 
}

Именно в этот момент я теряюсь как person.PersonDetails.ContactInformation.Count () == 0. Таким образом, ModelBinder создал объект ContactInformation, но не заполнил его объектом, который он должен содержать (т.е. ContactData) с индексом 0.

У меня вопрос в два раза: 1. Я выбрал правильный подход ... то есть должна ли это работать? 2. Есть ли какие-либо идеи относительно того, почему не удается заполнить объект ContactInformation?

Большое спасибо, Ричард

Ответы [ 6 ]

21 голосов
/ 20 мая 2009

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

public ActionResult Create( 
    Person person,
    [Bind(Prefix="Person.PersonDetails")]
    PersonDetails details,
    [Bind(Prefix="Person.PersonDetails.ContactInformation")] 
    ContactInformation[] info )
{
      person.PersonDetails = details;
      person.PersonDetails.ContactInformation = info;

      ...
}

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

5 голосов
/ 20 мая 2009

Если свойство имеет значение null, то связыватель модели другой не сможет его найти или не сможет найти значения в отправленной форме, необходимые для создания экземпляра типа свойства. Например, если свойство имеет необнуляемый идентификатор, а ваша форма не содержит никаких данных для этого идентификатора, связыватель модели оставит свойство как пустое, поскольку он не может создать новый экземпляр типа без знания идентификатора.

Другими словами, чтобы диагностировать эту проблему, вы должны тщательно сравнить данные в отправленной форме (это легко увидеть с помощью Firebug или Fiddler) со структурой объекта, который, как вы ожидаете, будет заполнен механизмом связывания моделей. Если какие-либо обязательные поля отсутствуют или значения представлены таким образом, что их невозможно преобразовать в тип обязательного поля, весь объект останется нулевым.

1 голос
/ 22 мая 2009

Я боролся с этим же типом сценария и в конце концов понял, что основная проблема заключается в том, что механизм связывания модели MVC по умолчанию не работает с полями EntitySet , только с полями List . Однако я нашел простой обходной путь, который кажется приемлемым. В моем случае у меня есть компания Company, которая имеет отношение один-ко-многим к контактам (мой набор сущностей Linq-to-Sql).

Поскольку кажется, что когда я изменяю свой код с EntitySet на List , механизм связывания модели MVC по умолчанию начинает работать, как и ожидалось (даже если LTS не работает сейчас), я решил предоставить альтернативный , свойство aliased для MVC, имеющее тип List , и, разумеется, это работает.

В классе моей компании:


// This is what LINQ-to-SQL will use:
private EntitySet<Contact> _Contacts = new EntitySet<Contact>();
[Association(Storage="_Contacts", OtherKey="CompanyID", ThisKey="ID")]
public EntitySet<Contact> Contacts
{
    get { return _Contacts; }
    set { _Contacts.Assign(value); }
}

// This is what MVC default model binder (and my View) will use:
public List<Contact> MvcContacts
{
    get { return _Contacts.ToList<Contact>(); }
    set { _Contacts.AddRange(value); }
}

Так что теперь, на мой взгляд, у меня есть следующее:

<label>First Name* <%= Html.TextBox("Company.MvcContacts[" + i + "].FirstName") %> </label> <label>Last Name* <%= Html.TextBox("Company.MvcContacts[" + i + "].LastName") %> </label>

Кажется, работает как шарм!

Удачи! -Mike

0 голосов
/ 11 февраля 2016

Убедитесь, что ваши модели (и все вложенные модели) используют свойства (получатели / установщики) вместо полей. Видимо, для связующего по умолчанию нужны свойства, чтобы функционировать должным образом. У меня была очень похожая ситуация, которая была исправлена ​​путем изменения необходимых полей в свойствах.

0 голосов
/ 20 мая 2009

Первый аргумент Html.TextBox - это имя текстового поля, второй - значение.

"Неправильный":

<%= Html.TextBox("person.PersonDetails.ContactInformation[0].Data")%>

"Право":

<%= Html.TextBox("nameoftextbox", person.PersonDetails.ContactInformation[0].Data)%>
0 голосов
/ 20 мая 2009

Возможно, отсутствует атрибут Bind:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create ([Bind] Person person)
{
// Do stuff to validate and add to the database 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...