Нужна помощь в использовании DefaultModelBinder для вложенной модели.

StackOverflow https://stackoverflow.com/questions/2563685

  •  23-09-2019
  •  | 
  •  

Вопрос

Есть несколько связанных вопросов, но я не могу найти ответ, который работает.

Предположим, у меня есть следующие модели:

public class EditorViewModel
{
  public Account Account {get;set;}
  public string SomeSimpleStuff {get;set;}
}

public class Account
{
  public string AccountName {get;set;}
  public int MorePrimitivesFollow {get;set;}
}

и взгляд, который простирается ViewPage<EditorViewModel> который делает следующее:

<%= Html.TextBoxFor(model => model.Account.AccountName)%>
<%= Html.ValidationMessageFor(model => model.Account.AccountName)%>
<%= Html.TextBoxFor(model => model.SomeSimpleStuff )%>
<%= Html.ValidationMessageFor(model => model.SomeSimpleStuff )%>

и мой контроллер выглядит так:

[HttpPost]
public virtual ActionResult Edit(EditorViewModel account)
{ /*...*/ }

Как я могу заставить DefaultModelBinder правильно связать мою EditorViewModel?Не делая ничего особенного, я получаю пустой экземпляр моей EditorViewModel со всем значением null или значением по умолчанию.

Ближе всего я пришел, позвонив UpdateModel вручную:

[HttpPost]
public virtual ActionResult Edit(EditorViewModel account)
{
    account.Account = new Account();
    UpdateModel(account.Account, "Account");
    // this kills me:
    UpdateModel(account);

Это успешно обновляет модель свойств моей учетной записи, но когда я вызываю UpdateModel account (чтобы получить остальные общедоступные свойства моей EditorViewModel) я получаю совершенно бесполезное сообщение «Модель типа...не удалось обновить.» Внутреннего исключения нет, поэтому я не могу понять, что происходит не так.

Что мне с этим делать?

Это было полезно?

Решение

Связующее устройство запутывается, поскольку видит, что параметр вашего метода действия имеет имя счет, и он видит входящие поля формы с именами account.accountname, поэтому он ищет свойство AccountName в вашей EditorViewModel.

Вы можете исправить это, переименовав параметр во что-то другое, что не конфликтует с входящим полем формы, или вы можете прикрепить к параметру атрибут [Bind(Prefix = "")].Этот атрибут говорит: «игнорируйте тот факт, что параметр назван счет, и притворимся, что вместо этого я дал ему пустое строковое имя.» Тогда связующий будет искать account.accountname вместо account.account.имя учетной записи.

Изменить - дополнительная информация:

Когда связующее видит сложный параметр с именем фу, он ищет в текущем запросе все, что имеет имя *foo.**.Итак, если ваш параметр был назван фу и его тип имел свойство с именем Имя, ожидается, что входящее значение будет foo.FirstName=Джон, например.

Однако если связыватель не видит *foo.** как часть запроса, он просто ищет * напрямую (без фу префикс).Итак, пока в запросе не было *foo.**, вы можете отправить Имя=Джон и переплетчик поймет это правильно.Но если в запросе есть *foo.**, Имя=Джон значение не будет соответствовать свойству FirstName.

Теперь вы можете видеть, как присвоение параметру вашего метода действия того же имени, что и одно из его свойств, нарушит эту логику.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top