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

How to pass the ViewModel edited with an ajax post

9 Answers 1983 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Leoni
Top achievements
Rank 1
Leoni asked on 17 Nov 2015, 01:27 PM

I would like to send a viewModel selected with edit "Edit" action grid to update this row data in controller side .
I would like then to send back the new version of row data : update Popup and datasource grid.

For now, the ajax post to send the edit row doesn't work fine. The data propertie of ajax call return an javascript Error.

Do you have a suggestion ? Thanks.

View :

 

@(Html.Kendo().Grid<KendoGridAjaxEditing.Models.ProductViewModel>()
      .Name("grid")
      .Columns(columns =>
      {
          columns.Bound(product => product.ProductName);
          
          columns.Bound(product => product.UnitsInStock).Width(250);
          columns.Command(commands =>
          {
              commands.Edit(); // The "edit" command will edit and update data items
              commands.Destroy(); // The "destroy" command removes data items
          }).Title("Commands").Width(200);
      })
        .Filterable(ftb => ftb.Mode(GridFilterMode.Row))
       .Scrollable()
       .Groupable()
        .Events(e =>
        {
             e.Edit("onRequestEdit"); // Ajax Call to update
        })
      .Editable(editable => editable.Mode(GridEditMode.PopUp)) // Use inline editing mode
      .DataSource(dataSource => dataSource
            .Ajax()
            .Model(model =>
            {
                model.Id(product => product.ProductID); // Specify the property which is the unique identifier of the model
                model.Field(product => product.ProductID).Editable(false).DefaultValue(0); // Make the ProductID property not editable
            })
            .Events(events =>
                    {
                    events.Error("onError");   
             })
            .ServerOperation(false)
            .Create(create => create.Action("Products_Create", "Home")) // Action invoked when the user saves a new data item
            .Read(read => read.Action("Products_Read", "Home"))  // Action invoked when the grid needs data
            .Update(update => update.Action("Products_Update", "Home"))  // Action invoked when the user saves an updated data item
            .Destroy(destroy => destroy.Action("Products_Destroy", "Home")) // Action invoked when the user removes a data item
      )
      .Pageable()
)

JavaScript (ajax call) :

 

function onRequestEdit(arg) {
        alert("onRequestEdit : Edit row");
         
        var griddata = $("#grid").data("kendoGrid");
         
        var uid = $(".k-edit-form-container").closest("[data-role=window]").data("uid");
        kendoConsole.log('onRequestEdit : Edit uid :' + uid);
        var model = $("#grid").data("kendoGrid").dataSource.getByUid(uid);
        // Show row value with currente model -> OK
        kendoConsole.log("onRequestEdit : Edit model : " + model.ProductID + ":" + model.ProductName);
        // Show row value with argument -> OK
kendoConsole.log("onRequestEdit : Edit argument : " + arg.model.ProductID + ":" + arg.model.ProductName);
        $.ajax({
            url: '@Url.Action("Products_CheckLock", "Home")',
            type: 'POST',
            datatype: 'json',
            contentType: "application/json; charset=utf-8",
            //data: JSON.stringify({ product: arg.model.data() }), // Return a javaScript Error
            //data: JSON.stringify({ product: arg.model() }), // Return a javaScript Error
            //data: JSON.stringify({ product: arg.model.dataSource(this) }), // Return a javaScript Error
            //data: JSON.stringify({ product: arg.model.dataSource.data() }), // Return a javaScript Error
            data: JSON.stringify({ product: arg.model.dataSource.data() }), // Return a javaScript Error
            success: function (result) {
                // Update record in Popup Edit
                // Is it a good way ?
                var grid = $("#grid").data("kendoGrid");
                var dataSource = new kendo.data.DataSource({
                        data: result.Data
                });
                grid.setDataSource(dataSource);
                grid.dataSource.refresh();
            },
            error: function () { alert('SM : Error Edit row'); }
        })
    }

Controller :

public ActionResult Products_CheckLock([DataSourceRequest]DataSourceRequest request, ProductViewModel[] product)
        //public ActionResult Products_CheckLock([DataSourceRequest]DataSourceRequest request, String product)
        {
            if (ModelState.IsValid)
            {
                using (var northwind = new NorthwindEntities())
                {
                    // Create a new Product entity and set its properties from the posted ProductViewModel
                    var entity = new Product
                    {
                        ProductID = product[0].ProductID,
                        ProductName = "Last_Version-" + product[0].ProductName,
                        UnitsInStock = product[0].UnitsInStock
                    };
                }
            }
            // Return the removed product. Also return any validation errors.
            return Json(new[] { product }.ToDataSourceResult(request, ModelState));
        }

 

9 Answers, 1 is accepted

Sort by
0
Maria Ilieva
Telerik team
answered on 19 Nov 2015, 12:41 PM
Hello Leoni,

I would suggest you to review the online demo below that demonstrates similar functionality:

http://demos.telerik.com/aspnet-mvc/grid/editing-popup


Regards,
Maria Ilieva
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Maria Ilieva
Telerik team
answered on 19 Nov 2015, 12:45 PM
Hi Leoni,

Also note that in the edit event you can get the object as JSON like this:

edit: function(arg){
  var itemData = JSON.stringify(arg.model.toJSON());
  alert(itemData);
},

I hope this helps.


Regards,
Maria Ilieva
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Leoni
Top achievements
Rank 1
answered on 19 Nov 2015, 03:50 PM

Hi Maria,

I don't understand your answer. How implement your answers in my case ?

I try to find a workaround with the classic editing capabilites of the MVC Grid for update the record before editing (custom Template). Indeed, I call the controller action to lock the record in database and get the last version record.  Thus the last version of record is displayed and locked during modifications.

Do you have a sample or suggestions to do that ?

Best regards.

 

 

0
Accepted
Maria Ilieva
Telerik team
answered on 24 Nov 2015, 08:15 AM
Hello,

The online demo that I have provided in my post demonstrates exactly the scenario that you want to achieve. Please try to follow it and let me know if you are facing issues in its implementation.
As for the code I have provided , it was given based on the comments you have left in the "onREquestEdit" method in your code and it demonstrates how to correctly stringify the model in the edit event.

Regards,
Maria Ilieva
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Leoni
Top achievements
Rank 1
answered on 25 Nov 2015, 11:52 AM

Hello Maria,

The online demo doesn't demontrate how update dynamicly the record with a ajax request in "onRequestEdit" event grid.
So I'm facing at the same issues :  How update the record in Popup after the ajax success event ? 
I tried to change my code as folllows, but the record doesn't updated client side (arg.model) :

 Is it a right way to do that ?  Thank for your help.

Controller :

public ActionResult Products_CheckLock([DataSourceRequest]DataSourceRequest request, String productReturn)
        {
            // Convert JSON TO OBJECT
            var product = JsonConvert.DeserializeObject<Product>(productReturn);
            if (ModelState.IsValid)
            {
                using (var northwind = new NorthwindEntities())
                {
                    // Create a new Product entity and set its properties from the posted ProductViewModel
                    var entity = new Product
                    {
                        ProductID = product.ProductID,
                        // UPDATE FIELD TO SIMULATE NEW VERVION RECORD
                        ProductName = "Last_Version-" + product.ProductName,
                        UnitsInStock = product.UnitsInStock
                    };
                    product = entity;
                }
            }
            // Return the last version product. Also return any validation errors.
            return Json(new[] { product }.ToDataSourceResult(request, ModelState));
        }

View :

@(Html.Kendo().Grid<KendoGridAjaxEditing.Models.ProductViewModel>()
      .Name("grid")
      .Columns(columns =>
      {
          columns.Bound(product => product.ProductID);
          columns.Bound(product => product.ProductName);
          columns.Bound(product => product.UnitsInStock).Width(350);
          columns.Command(commands =>
          {
              commands.Edit(); // The "edit" command will edit and update data items
              commands.Destroy(); // The "destroy" command removes data items
          }).Title("Commands").Width(200);
      })
        .Filterable(ftb => ftb.Mode(GridFilterMode.Row))
       .Scrollable()
       .Groupable()
       .Events(e =>
       {
        e.Edit("onRequestEdit"); // CALL AJAX FOR LOCK AND UPDATE RECORDS
       })
      .Editable(editable => editable.Mode(GridEditMode.PopUp)) // USE POPUP EDITING MODE
      .DataSource(dataSource => dataSource
            .Ajax()
            .Model(model =>
            {
                model.Id(product => product.ProductID);
                model.Field(product => product.ProductID).Editable(false).DefaultValue(0);
            })
            .Events(events =>
                    {
                    events.Error("onError");
             })
            .ServerOperation(false)
            .Create(create => create.Action("Products_Create", "Home"))
            .Read(read => read.Action("Products_Read", "Home")) 
            .Update(update => update.Action("Products_Update", "Home")) 
            .Destroy(destroy => destroy.Action("Products_Destroy", "Home"))
      )
      .Pageable()
)

Javascript :

// Event : Edit Record : CALL AJAX TO LOCK/UPDATE RECORD
    function onRequestEdit(arg) {
        var model = arg.model;
        $.ajax({
            url: '@Url.Action("Products_CheckLock", "Home")',
            type: 'POST',
            datatype: 'json',
            data: { productReturn: JSON.stringify(model) }, // OK
            edit : function(arg){ // THIS DOESN'T WORK : // NEVER CALL
                var itemData = JSON.stringify(arg.model.toJSON());
                alert("edit:" + itemData);
            },
            success: function (data) {
                var itemData = JSON.stringify(data);
                alert("success:" + itemData);
 
                //model.dataSource(data); // DOESN'T WORK
                //arg.model.data = data; // DOESN'T WORK
                //arg.model.set(data.fieldName, data.values); // DOESN'T WORK
                //self.updateModel(data); // DOESN'T WORK : Undefined
 
                // HOW UPDATE RECORD AND POPUP WTIH LAST VERSION RECORD ???
                 
                
            },
            error: function () { alert('SM : Error Ajax'); }
        })
    }

0
Leoni
Top achievements
Rank 1
answered on 27 Nov 2015, 11:14 AM
Additional information :
0
Dimo
Telerik team
answered on 27 Nov 2015, 02:43 PM
Hi Leoni,

The correct syntax to set a model value in the success handler is:

arg.model.set("field name as string", "value as appropriate data type");

http://docs.telerik.com/kendo-ui/api/javascript/data/model#methods-set
 
http://docs.telerik.com/kendo-ui/api/javascript/data/observableobject#methods-set

There are two things in the provided code, which I don't understand:

1) why is there an edit callback defined in the $.ajax() call, as such an option does not exist
2) why the Ajax response in the success callback is stringified instead of parsed

I am not sure what is the exact Ajax response that is returned to the client, but in all cases, the set() method above should be using a valid field name and a valid value of the expected data field type.

Regards,
Dimo
Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Mike
Top achievements
Rank 1
answered on 11 Aug 2016, 05:43 PM

Hi Maria -

No  where in the code for the demo you provided does it explain how the viewmodel is getting passed back to the controller action for update.  If you take the demo code using the controller actions and the grid definition & place it in a project (wiring up the correct fields to a valid datasource) - the application displays the data but it does not call any of the controller actions defined.  It actually causes a '500 Internal Server Error' with the following unhandled exception:

[MissingMethodException: No parameterless constructor defined for this object.]

I understand that this error is thrown because the controller action is expecting parameters but the demo does not provide any info on how those parameters are to be sent from the client-side.

Do we need to create javascript functions to handle calling the controller actions for update, etc like Leoni has done with the following code:

.Events(e =>
        {
             e.Edit("onRequestEdit"); // Ajax Call to update

        })

Any information would be appreciated.

 

Thanks

0
Dimo
Telerik team
answered on 15 Aug 2016, 08:18 AM
Hello Mike,

Normally, you do not need to do anything special to submit the updated model back to the controller's action method, as this is taken care of by the client-side Grid DataSource instance.

The mentioned error can be caused by incorrect configuration or binding to an object type with no paramerless constructor:

http://www.telerik.com/forums/no-parameterless-constructor-defined-for-this-object-when-updating-grid

http://www.telerik.com/forums/no-parameterless-constructor-defined-for-this-object-62a76c3339f1

Please check the following resources and compare them with your implementation.

Ajax binding
http://docs.telerik.com/kendo-ui/aspnet-mvc/helpers/grid/binding/ajax-binding

Ajax editing
http://docs.telerik.com/kendo-ui/aspnet-mvc/helpers/grid/editing/ajax-editing

Server binding
http://docs.telerik.com/kendo-ui/aspnet-mvc/helpers/grid/binding/server-binding

Server editing
http://docs.telerik.com/kendo-ui/aspnet-mvc/helpers/grid/editing/server-editing

I also recommend reviewing the offline ASP.NET MVC examples, which are provided in the UI for ASP.NET MVC installer. This will make checking the relationships between the models and controllers easier.

If the cause of the issue remains unclear, please send us an isolated runnable project and we will inspect it.

Regards,
Dimo
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
Grid
Asked by
Leoni
Top achievements
Rank 1
Answers by
Maria Ilieva
Telerik team
Leoni
Top achievements
Rank 1
Dimo
Telerik team
Mike
Top achievements
Rank 1
Share this question
or