Kendo Grid model with an IEnumerable property not updating correctly after Create/Update when using AJAX binding
So In case anyone stumbles on this in the future, I contacted Telerik support, who explained to me that:
The dataSource supports only value types and will not serialize the arrays in the format that is expected by the model binder.
They also provided me with a workaround using the request Data function to call a JavaScript function which converts the data into the correct format.
In the view, modify the request functions by specifying the name of the JavaScript function to call:
.Create(create => create.Action("AddNote", "ReleaseNotes").Data("serialize"))
And then add in the functions which will do the conversion:
function serialize(data) {
for (var property in data) {
if ($.isArray(data[property])) {
serializeArray(property, data[property], data);
}
}
}
function serializeArray(prefix, array, result) {
for (var i = 0; i < array.length; i++) {
for (var property in array[i]) {
result[prefix + "[" + i + "]." + property] = array[i][property];
}
}
}
Alejo
Updated on June 28, 2022Comments
-
Alejo almost 2 years
I'm having a problem where a property of my model is not being correctly updated when sending it to my controller for an Update or Create call from a Kendo Grid. The model looks like this:
public class ReleaseNotesModel { public int NoteID { get; set; } public int ReleaseID { get; set; } public List<TranslationModel> ReleaseNoteTranslations { get; set; } public ReleaseNoteType ItemType { get; set; } } public class TranslationModel { public int TranslationID { get; set; } public string Translation { get; set; } public int LanguageID { get; set; } public int ItemID { get; set; } }
Here is the grid in my view:
@(Html.Kendo().Grid<ReleaseNotesModel>() .Name("Grid") .Columns(columns => { columns.Bound(m => m.ItemType).Width(140); columns.Bound(m => m.Description); columns.Command(command => { command.Edit(); command.Destroy(); }).Width(170); }) .ToolBar(toolbar => toolbar.Create()) .Editable(editable => editable .Mode(GridEditMode.PopUp) .TemplateName("ReleaseNoteTemplate") .Window(w => w.Width(620)) .DisplayDeleteConfirmation(true) ) .Pageable() .Sortable() .Scrollable() .Filterable() .DataSource(dataSource => dataSource .Ajax() .ServerOperation(false) //.Server() .Events(e => e.Error("grid_error")) .Model(model => { model.Id(m => m.NoteID); model.Field(m => m.ReleaseID).DefaultValue(Model.ReleaseID); model.Field(m => m.ItemType).DefaultValue(ReleaseNoteType.NewFeature); //defaultTranslationsList is a List<TranslationModel> with two empty objects in it model.Field(m => m.ReleaseNoteTranslations).DefaultValue(defaultTranslationsList); }) .PageSize(5) .Read(read => read.Action("GetNotes", "ReleaseNotes", new { releaseID = Model.ReleaseID })) .Create(create => create.Action("AddNote", "ReleaseNotes")) .Update(update => update.Action("EditNote", "ReleaseNotes")) .Destroy(destroy => destroy.Action("DeleteNote", "ReleaseNotes")) ) )
So more specifically, the problem I am having is that in my controller action:
public async Task<ActionResult> EditNote(ReleaseNotesModel model)
model.ReleaseNoteTranslations
always contains two empty objects (properties are null or 0), i.e. the default value which I set for this property. If I set no default value, then I won't have any fields to edit for this property in the popup editor. All the other properties are updated as expected.What bugs me is that if I use server binding instead of AJAX, then all the data is correctly received. So I decided to check out the data in the request headers being sent in both cases:
// Using server binding ReleaseID:300 NoteID:886 ItemType:1 ReleaseNoteTranslations[0].ItemID:886 ReleaseNoteTranslations[0].LanguageID:1 ReleaseNoteTranslations[0].TranslationID:869 ReleaseNoteTranslations[0].Translation:The module is now released! ReleaseNoteTranslations[1].ItemID:886 ReleaseNoteTranslations[1].LanguageID:2 ReleaseNoteTranslations[1].TranslationID:870 ReleaseNoteTranslations[1].Translation:Le module est maintenant disponible! NoteID:886 // Using AJAX binding sort: group: filter: NoteID:886 ReleaseID:300 ReleaseNoteTranslations[0][TranslationID]:869 ReleaseNoteTranslations[0][Translation]:The module is now released! ReleaseNoteTranslations[0][LanguageID]:1 ReleaseNoteTranslations[0][ItemID]:886 ReleaseNoteTranslations[1][TranslationID]:870 ReleaseNoteTranslations[1][Translation]:Le module est maintenant disponible! ReleaseNoteTranslations[1][LanguageID]:2 ReleaseNoteTranslations[1][ItemID]:886 ItemType:1
Now what I notice first here is the syntax of
objectName[index].PropertyName
vsobjectName[index][PropertyName]
I wonder if this could be the cause of my problem, and if so, is there a way for me to go and directly manipulate the data being sent to fix it? Could this be a bug in the way Kendo Grid sends data through Ajax binding?
Either way, any help would be much appreciated!