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

Problem with updates using Kendo Grid with MVC 4 web api Controller

4 Answers 1338 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Alex VonBrand
Top achievements
Rank 1
Alex VonBrand asked on 09 Jul 2012, 03:08 PM
I am trying to use the kendo Grid with an mvc 4 web api Controller using JSON.  I am using kendoui.web.2012.1.515.commercial.
The problem is that the updates from the grid are not pushed to the web service.

The script imports on the page are as follows:

<link href="/students/Content/kendo/kendo.common.min.css" rel="stylesheet" type="text/css" />
<link href="/students/Content/kendo/kendo.default.min.css" rel="stylesheet" type="text/css" />
<script src="/students/Scripts/jquery-1.7.2.js" type="text/javascript"></script>
<script src="/students/Scripts/Kendo/kendo.core.js" type="text/javascript"></script>
<script src="/students/Scripts/Kendo/kendo.web.js" type="text/javascript"></script>
<script src="/students/Scripts/Kendo/kendo.data.js" type="text/javascript"></script>
<script src="/students/Scripts/Kendo/kendo.grid.js" type="text/javascript"></script>



Here is the code for the grid:

 $("#grid").kendoGrid({
        dataSource: dataSource,

        height: 600,
        filterable: true,
        sortable: true,
        pageable: true,
        toolbar: ["create", "save", "cancel"],
       columns: [
       {
            field: "StudentID",
            filterable: false
        },

                            "FullName",
                            {
                                field: "BirthDate",
                                title: "Birth Date",
                                width: 100,
                                format: "{0:MM/dd/yyyy}",
                                editor: function (container, options) {
                                    $('<input id=\"' + options.field + '\" />').appendTo(container)
                                     .kendoDatePicker({ format: "MM/dd/yyyy" });

                                    var datePicker = $("#BirthDate").data("kendoDatePicker");
                                    // bind to the close event
                                    datePicker.bind('close', function (e) {
                                        // See what the datepicker is returning:
                                        var datepicker = e.sender.element.kendoDatePicker();
                                        var d = new Date(datepicker.val());
                                    });

                                }

                        },  {
                                field: "Gender",
                                title: "Gender"
                            },
                         { command: ["edit"], title: "&nbsp;", width: "210px"}],
                          editable: "inline"

    });

the code for the datasource is:

 var     dataSource = new kendo.data.DataSource(   
            transport: {
                read: { url: "/students/api/EmergData/GetStudentList/STARRGAY",
                    dataType: "json",

                    type: "POST",
                    contentType: "application/json; charset=utf-8"
                },
                update: {
                    url: "/students/api/EmergData/UpdateEmerStuds/",
                    dataType: "json",
                    type: "POST",
                    contentType: "application/json; charset=utf-8"

                },

                parameterMap: function (options, operation) {
                    if (operation !== "read" && options) {

             //  return { models: kendo.stringify(options.models) };          
                       
   return kendo.stringify(options);
                    
                    }
                }
            },

            schema: {
             
                model: {
                    id: "StudentID",
                    fields: {
                        StudentID: { editable: false, nullable: true },

                        FullName: { type: "string" },
                        BirthDate: { type: "date" },
                        Grade: { type: "string" },
                        Gender: { type: "string" }
                    }
                }
            },
            pageSize: 30,
            serverPaging: false,
            serverFiltering: false,
            serverSorting: false
        });

first I tried inline editing.  When I edited a cell in the grid, I found that the set: method in kendo.data.js fired
and apparently set the dirty flag of the edited object:

that.dirty = true;

But then when I clicked update and the code in the sync: method in kendo.data.js fired, the data object in the underlying array had its dirty flag still set to false and the field that had been edited was still its orginal value.

I went back the set method and overrode it in this way:

kendo.data.Model.fn.set = function (field, value, initiator) {
    var that = this;
    if (that.editable(field)) {
        value = that._parse(field, value);

        if (value != that.get(field)) {
            that.dirty = true;

            for (var i = 0; i < data.length; i++) {
                if (data[i].id === that.id) {
                    data[i].dirty = true;
                    for (var prop in data[i]) {
                        if (prop == field) {
                            data[i][prop] = value;
                        }
                    }
                }
            }
           // ObservableObject.fn.set.call(that, field, value, initiator);
        }
    }
}

Now when I clicked the update link, my update was sent to the web api method, but I got a model binding error.
I changed the code in the parametermap property of the gird from the form I had gotten from the inline demo:

parameterMap: function (options, operation) {
                    if (operation !== "read" && options) 
                  //  return { models: kendo.stringify(options.models) };
                        return kendo.stringify(options);        
                    }
                }
            },

I found that the models property was always null, but that the options object itself was the javascript object that represented the data of the row. 

Now my updates got posted correctly to the the web api method and the database got updated.
I then tried to switch this over to the batch updating but for some reason this did not work.

So it seems that the statement in the set method is not working for me:

ObservableObject.fn.set.call(that, field, value, initiator);

I do notice that the initiator object is always null when this method gets called but I am not sure if this is a problem or not.

Any ideas what is going on? or how I can get this working for inline without the hack?  or how I can get this to work at all with bach editing?

Thanks,
Alec von Brand
MCPS

 

 

 

 

 

 

 

function (options, operation) {

 

 

 

 

 

if (operation !== "read" && options) {

 

 

 

 

 

var data = kendo.stringify(options);

 

 

 

 

 

var json = JSON.stringify(options);

 

 

 

 

 

// return { models: JSON.stringify(options.models) };

 

 

 

 

 

return kendo.stringify(options);

 

 

 

 

 

// return { models: kendo.stringify(options.models) };

 

 

 

 

 

// return { models: ko.toJSON(options.models) };

}

}

},

 

 

 

 

 

 

 

 

 

function (options, operation) {

 

 

 

 

 

if (operation !== "read" && options) {

 

 

 

 

 

var data = kendo.stringify(options);

 

 

 

 

 

var json = JSON.stringify(options);

 

 

 

 

 

// return { models: JSON.stringify(options.models) };

 

 

 

 

 

return kendo.stringify(options);

 

 

 

 

 

// return { models: kendo.stringify(options.models) };

 

 

 

 

 

// return { models: ko.toJSON(options.models) };

}

}

},

 

 

 

 

 

 

 

 

 

function (options, operation) {

 

 

 

 

 

if (operation !== "read" && options) {

 

 

 

 

 

var data = kendo.stringify(options);

 

 

 

 

 

var json = JSON.stringify(options);

 

 

 

 

 

// return { models: JSON.stringify(options.models) };

 

 

 

 

 

return kendo.stringify(options);

 

 

 

 

 

// return { models: kendo.stringify(options.models) };

 

 

 

 

 

// return { models: ko.toJSON(options.models) };

}

}

},

 

 

 

 


4 Answers, 1 is accepted

Sort by
0
Juan Manuel
Top achievements
Rank 1
answered on 10 Jul 2012, 06:55 AM
Hi!

This probably because web api controller uses the default DataContractSerializer and it returns the ouput as XML and probably kendo grid is expecting json.

In the next article you can see how to create a JsonFormatter with Json.Net and use it insted the DatContractSerializer: 
http://blogs.msdn.com/b/henrikn/archive/2012/02/18/using-json-net-with-asp-net-web-api.aspx
http://code.msdn.microsoft.com/Using-JSONNET-with-ASPNET-b2423706
http://codepaste.net/dfz984

The configure your Global.asax in the application start event to use it:

GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonNetFormatter());


I hope this works for you cause it did it for me

Cya!
0
Alex VonBrand
Top achievements
Rank 1
answered on 10 Jul 2012, 02:26 PM
Juan,

Thanks for your reply.  The links you provided were interesting.

Actually though, the json from the web api is working ok.  The grid binds fine to the the data from the service.  So the problem is not with the data type returned from the server.
The problem is with the update on the grid.  When I update a row, a method in the kendo.data.js library called "set"  fires.  I can see the update being made on an internal data record, its dirty flag is set to true and the field is updated.

However, when I acutually click the update link on the grid, a method in kendo.data.js called "sync" fires.  In this method, a check is made of the underlying array of data records of the grid datasource to check which ones have been changed, so that these changes can be flushed to the web service.

At this point, no records are found in that array with a dirty flag set to true.  So, from datasource's point of view nothing has been udated, so nothing gets sent to the service.

So the problem seems to be that the observable in the datasoruce is not correctly updating the underlying data source when  a record is changed on the grid.

I have been able to make this work by hacking the set method in kendo.data.js but I am not very happy with hacking the library if I ever want to use this code in production. 

So what I am looking for is a way to get the grid updates to work as per expected functionality.
0
Blake
Top achievements
Rank 1
answered on 17 Jul 2012, 07:15 PM
It seems that we are both running into the same issue (http://www.kendoui.com/forums/ui/grid/please-help-grid-inline-updating-not-working.aspx#2190650). The JSON is returned fine, the issue is with the GRID logic for updates is not working.

Where you able to come to an official solution?
0
Morten
Top achievements
Rank 2
Iron
Iron
Veteran
answered on 03 Jun 2014, 06:13 PM
I think I had the same issue: A grid bound to a datasource with inline editing. The grid loaded data just fine (read), entered edit mode (and exited edit mode on cancel clicked), and sent data back to the server (handled by an asp.net mvc controller function. However, the row didn't exit edit-mode once the asp.net mvc controller function returned the value.

It turned out that the problem was the return value of the asp.net mvc controller function was a bool and not JsonResult. Once I change the type of the return value to JsonResult the row did exit edit mode.


Tags
Grid
Asked by
Alex VonBrand
Top achievements
Rank 1
Answers by
Juan Manuel
Top achievements
Rank 1
Alex VonBrand
Top achievements
Rank 1
Blake
Top achievements
Rank 1
Morten
Top achievements
Rank 2
Iron
Iron
Veteran
Share this question
or