2009-05-20 2 views
8

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

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

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

person.PersonDetails.ContactInformation[0].Data; 

Этот класс структура, созданный LinqToSql и ContactInformation имеет тип EntitySet<ContactData>. Для того, чтобы создать представление я прохожу следующее:

return View(person); 

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

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

Сообщение метод в мой контроллер затем следующим образом:

[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?

Большое спасибо, Richard

ответ

20

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

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; 

     ... 
} 

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

+1

Спасибо, что работает отлично. Я пробовал пример с гораздо более глубокой иерархией, которая работала отлично, но вы, вероятно, правы, что она теряется в сложности. Два комментария, однако, для ясности: 1. Мне понадобился только [Bind (Prefix = «Person.PersonDetails.ContactInformation»)] ContactInformation [] info) и соответствующая настройка объекта модели. 2. ContactInformation [] должен быть EntitySet для правильного отображения. Теперь, чтобы найти более подробную информацию о префиксе .... Спасибо за помощь. Richard – Richbits

+0

Ничего, еще не читал о 'префиксах'! – Ropstah

+0

good one. Или вы могли бы разработать собственное собственное связующее устройство, которое бы понимало, как вывести сложную модель из входов формы, можете ли вы обмениваться ссылкой или имплицировать. если u hv уже сделано? –

0

Возможно отсутствие привязок атрибута является случай:

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

Спасибо, я дал эту попытку без везения. Тот факт, что он привязан к человеку и создает объекты до объекта ContactInformation, указывает на то, что он является обязательным, а не уровнем ContactData. – Richbits

+0

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

0

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

"Wrong":

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

"Right":

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

Спасибо, но я понимаю, что вторым параметром является значение, используемое для заполнения текстового поля в, например, сценарий редактирования. Первое значение используется установкой defaultmodelbinder для привязки формы к объекту, созданному при отправке назад. – Richbits

+0

My bad ........... – Ropstah

5

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

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

+2

Звучит правильно. –

+0

Спасибо, конечно, если то, что вы здесь говорите, правильно, тогда решение tvanfossen тоже потерпит неудачу? – Richbits

+0

Не обязательно.Я описываю одну возможную проблему. Он описывает другого. –

1

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

Так как кажется, что когда я изменить мой код из EntitySet < Контакт > к списку < Связаться с >, то MVC модель по умолчанию Связующее начинает работать, как ожидалось (даже несмотря на то, LTS не сейчас), я полагал, что обеспечит alternate, свойство «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

Спасибо, извините, ненадолго. Надеюсь, что вы ответили на это на MSDN (я предполагаю, что это вы прокомментировали там). Я также зарегистрировал ошибку на сайте подключения, и это подтверждено, исправлено в .Net 4.0. В моем случае я считаю, что ваше решение становится слишком сложным, поскольку набор объектов находится глубоко внутри моей структуры класса. Я также обнаружил, что редактирование EntitySets является реальной проблемой, поскольку новая строка db создается вместо обновления. Надеюсь, это тоже будет разобрано в 4.0. – Richbits

+0

Приятно слышать, что это будет рассмотрено. И да, я опубликовал это же решение для группы новостей Майкрософт практически в то же время, что и я здесь: до сих пор я не понимал, что вы тот, кто его начал! Вы получили один ответ от Аллена, который показывает, как исправить свойство-сеттер, который кажется более идеальным, но в моем случае я использую объекты, созданные LTS, и не знаю, как легко это исправить (без, конечно, более гигантских обходных решений). P.S., другой поток находится здесь: http://groups.google.com/group/microsoft.public.dotnet.framework.aspnet/browse_thread/thread/a2869970f33c712a/188c0a9e5c00dc2a – Funka

0

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

Смежные вопросы