This is a migrated thread and some comments may be shown as answers.

nested model does not bind properly on batch mode submit

1 Answer 127 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Software
Top achievements
Rank 1
Software asked on 12 Dec 2012, 04:49 PM
I have a nested ViewModel structure, with a custom editor on the grid that can edit the List of 'Items' on the QuestionLifeCycleAssignmentViewModel.

Here is the ViewModel:
public class AssignedQuestionViewModel
{
    public int QuestionTemplateId { get; set; }
    public int QuestionGroupTemplateId { get; set; }
    public string QuestionText { get; set; }
    public bool Required { get; set; }
    public string RequiredCheckedString { get; set; }
    public QuestionLifeCycleAssignmentViewModel LifeCycle { get; set; }
}
 
public class QuestionLifeCycleAssignmentViewModel
{
    public List<QuestionLifeCycleAssignmentItemViewModel> Items { get; set; }
    public string SelectedLifeCycleCsvList { get; set; }
}
 
public class QuestionLifeCycleAssignmentItemViewModel
{
    public string LifeCycleDescription { get; set; }
    public int LifeCycleId { get; set; }
    public bool Assigned { get; set; }
    public string LifeCycleAbbreviation { get; set; }
 
}

Here is the View:
@(Html.Kendo().Grid<AssignedQuestionViewModel>()
      .Name("Questions_#=QuestionGroupTemplateId#")
      .Columns(columns =>
                   {
                       columns.Bound(i => i.QuestionTemplateId).Hidden();
                       columns.Bound(i => i.QuestionGroupTemplateId).Hidden();
                       columns.Bound(i => i.Required);
                       columns.Bound(i => i.QuestionText);
                       columns.Bound(i => i.LifeCycle).ClientTemplate("\\#=LifeCycle.SelectedLifeCycleCsvList\\#");
                   }
      )
      .ToolBar(toolBar => toolBar.Save())
      .Editable(editable => editable.Mode(GridEditMode.InCell))
      .DataSource(dataSource => dataSource
                                    .Ajax()
                                    .Batch(true)
                                    .ServerOperation(false)
                                    .Model(model =>
                                               {
                                                   model.Id(m => m.QuestionTemplateId);
                                                   model.Field(m => m.QuestionTemplateId).Editable(false);
                                                   model.Field(m => m.QuestionGroupTemplateId).Editable(false);
                                                   model.Field(m => m.QuestionText).Editable(false);
                                               })
                                    .Read(read => read.Action("ReadAssignedQuestions", "QuestionManagement", new { p = "#=QuestionGroupTemplateId#"})
                                                      .Type(HttpVerbs.Post)                                                         
                                    )
                                    .Update(update => update.Action("SaveAssignedQuestions", "QuestionManagement"))
      )
      .Events(e => e.Edit("testEvent"))
      .ToClientTemplate()
      )

Here is the Controller:
[HttpPost]
  [HandleJsonException]
  public ActionResult SaveAssignedQuestions([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")] IEnumerable<AssignedQuestionViewModel> models)
  {
      var result = _questionManagementHelper.SaveQuestionAssignmentEdits(models);
      return Json(GetJsonResponse(result, "An error occurred saving assigned question edits."));
  }

Breaking in the controller, copied from the Watch window:

-       LifeCycle   {Esurety.Core.ViewModels.QuestionManagement.QuestionLifeCycleAssignmentViewModel}   Esurety.Core.ViewModels.QuestionManagement.QuestionLifeCycleAssignmentViewModel
-       Items   Count = 6   System.Collections.Generic.List<Esurety.Core.ViewModels.QuestionManagement.QuestionLifeCycleAssignmentItemViewModel>
-       [0] {Esurety.Core.ViewModels.QuestionManagement.QuestionLifeCycleAssignmentItemViewModel}   Esurety.Core.ViewModels.QuestionManagement.QuestionLifeCycleAssignmentItemViewModel
        Assigned    false   bool
        LifeCycleAbbreviation   null    string
        LifeCycleDescription    null    string
        LifeCycleId 0   int
It is kind of hard to read, but you can see that the List of Items has 6 Items, which is a property of LifeCycle, which is a property of the top-level AssignedQuestionViewModel.  Everything is correct (the count of items is correct), except the Items have no values (you can see the nulls and 0 for the ID, and Assigned is always false even when it isn't supposed to be).  When I inspect in fiddler, using the WebForms tab, the data is correct, so it is being submitted, it is the binding that is not working correctly.  Here is from Fiddler WebForms:

group
filter
models[0].QuestionTemplateId 1
models[0].QuestionGroupTemplateId 1
models[0].QuestionText First Name
models[0].Required true
models[0].RequiredCheckedString checked
models[0].LifeCycle.Items[0][LifeCycleDescription] Bond Application
models[0].LifeCycle.Items[0][LifeCycleId] 1
models[0].LifeCycle.Items[0][Assigned] true
models[0].LifeCycle.Items[0][LifeCycleAbbreviation] Nb

And here is the TextView:

sort=&group=&filter=&models%5B0%5D.QuestionTemplateId=1&models%5B0%5D.QuestionGroupTemplateId=1&models%5B0%5D.QuestionText=First+Name&models%5B0%5D.Required=true&models%5B0%5D.RequiredCheckedString=checked&models%5B0%5D.LifeCycle.Items%5B0%5D%5BLifeCycleDescription%5D=Bond+Application&models%5B0%5D.LifeCycle.Items%5B0%5D%5BLifeCycleId%5D=1&models%5B0%5D.LifeCycle.Items%5B0%5D%5BAssigned%5D=true&models%5B0%5D.LifeCycle.Items%5B0%5D%5BLifeCycleAbbreviation%5D=Nb&models%5B0%5D.LifeCycle.Items%5B1%5D%5BLifeCycleDescription%5D=Renewal&models%5B0%5D.LifeCycle.Items%5B1%5D%5BLifeCycleId%5D=2&models%5B0%5D.LifeCycle.Items%5B1%5D%5BAssigned%5D=true&models%5B0%5D.LifeCycle.Items%5B1%5D%5BLifeCycleAbbreviation%5D=Rw&models%5B0%5D.LifeCycle.Items%5B2%5D%5BLifeCycleDescription%5D=Cancellation&models%5B0%5D.LifeCycle.Items%5B2%5D%5BLifeCycleId%5D=4&models%5B0%5D.LifeCycle.Items%5B2%5D%5BAssigned%5D=false&models%5B0%5D.LifeCycle.Items%5B2%5D%5BLifeCycleAbbreviation%5D=Cn&models%5B0%5D.LifeCycle.Items%5B3%5D%5BLifeCycleDescription%5D=Reinstatement&models%5B0%5D.LifeCycle.Items%5B3%5D%5BLifeCycleId%5D=6&models%5B0%5D.LifeCycle.Items%5B3%5D%5BAssigned%5D=false&models%5B0%5D.LifeCycle.Items%5B3%5D%5BLifeCycleAbbreviation%5D=Ri&models%5B0%5D.LifeCycle.Items%5B4%5D%5BLifeCycleDescription%5D=NonPBR&models%5B0%5D.LifeCycle.Items%5B4%5D%5BLifeCycleId%5D=7&models%5B0%5D.LifeCycle.Items%5B4%5D%5BAssigned%5D=false&models%5B0%5D.LifeCycle.Items%5B4%5D%5BLifeCycleAbbreviation%5D=Np&models%5B0%5D.LifeCycle.Items%5B5%5D%5BLifeCycleDescription%5D=PBR&models%5B0%5D.LifeCycle.Items%5B5%5D%5BLifeCycleId%5D=8&models%5B0%5D.LifeCycle.Items%5B5%5D%5BAssigned%5D=false&models%5B0%5D.LifeCycle.Items%5B5%5D%5BLifeCycleAbbreviation%5D=Pb&models%5B0%5D.LifeCycle.SelectedLifeCycleCsvList=Nb%2CRw


Thanks!
Danny

1 Answer, 1 is accepted

Sort by
0
Daniel
Telerik team
answered on 14 Dec 2012, 03:24 PM
Hello Danny,

Currently we do not serialize nested arrays if a format that will be processed by the model binder. We will improve the serialization for future versions so that it supports this scenario. For now I can suggest to use the Update request Data function to convert the data in the correct format("collectionPropertyName[index].propertyName"). From the snippet you shared it seems that the code should be as below:

function convert(data) {
    var models = data.models;
    for (var i = 0; i < models.length; i++) {
        var items = models[i].LifeCycle.Items;
        if (items) {
            for (var j = 0; j < items.length; j++) {
                for (var property in items[j]) {
                    models[i]["LifeCycle.Items[" + j + "]." + property] = items[j][property];
                }  
            }
        }
    }
}
Regards,
Daniel
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
Tags
Grid
Asked by
Software
Top achievements
Rank 1
Answers by
Daniel
Telerik team
Share this question
or