Связывание модели вложенных свойств в asp.net mvc

Я хочу, чтобы в моем приложении mvc работала какая-то привязка. Я обнаружил, что вложенные свойства не связаны автоматически привязкой модели по умолчанию в выпуске RC1 asp.net mvc. У меня следующая структура классов:

public class Contact{  
    public int Id { get; set; }  
    public Name Name { get; set; }  
    public string Email { get; set; }  
}

Где Name определяется как:

public class Name{  
    public string Forename { get; set; }  
    public string Surname { get; set; }  
}

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

using(Html.BeginForm()){  
    Html.Textbox("Name.Forename", Model.Name.Forename);  
    Html.Textbox("Name.Surname", Model.Name.Surname);  
    Html.Textbox("Email", Model.Email);  
    Html.SubmitButton("save", "Save");  
}

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

public ActionResult Save(int id, FormCollection submittedValues){  
    Contact contact = get contact from database;  
    UpdateModel(contact, submittedValues.ToValueProvider());  

    //at this point the Name property has not been successfully populated using the default model binder!!!
}

Email Свойство успешно связаны , но не Name.Forename или Name.Surname свойства. Может ли кто-нибудь сказать, должно ли это работать, используя привязку модели по умолчанию, и я делаю что-то не так, или это не работает, и мне нужно свернуть свой собственный код для привязки вложенных свойств к объектам модели?

Ответов (3)

Решение

Я думаю, что проблема связана с префиксом Name в свойствах. Думаю, вам нужно обновить его как две модели и указать префикс для второй. Обратите внимание, что я удалил FormCollection из параметров и использовал сигнатуру, UpdateModel которая опирается на встроенный поставщик значений и указывает белый список свойств для рассмотрения.

 public ActionResult Save( int id )
 {
     Contact contact = db.Contacts.SingleOrDefault(c => c.Id == id);

     UpdateModel(contact, new string[] { "Email" } );
     string[] whitelist = new string[] { "Forename", "Surname" };
     UpdateModel( contact.Name, "Name", whitelist );
 }

Чтобы привязать имя, а не всю модель представления в POST, нужно указать привязке модели, что будет использоваться префикс. Это делается с помощью BindAttribute.

public ActionResult AddComment([Bind(Prefix = "Name")] Name name)
{
  //do something
}

Это очень интересно, потому что если бы вы сделали

public ActionResult Save( int id, Contact contact )
{
    //contact here would contain the nested values.
}

Пользуюсь этим с большим успехом. Я полагаю, тогда вы могли бы каким-то образом синхронизировать два объекта Contact вместе.

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