How to pass the ViewModel edited with an ajax post

10 posts, 1 answers
  1. Leoni
    Leoni avatar
    9 posts
    Member since:
    Jul 2012

    Posted 17 Nov 2015 Link to this post

    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));
            }

     

  2. Maria Ilieva
    Admin
    Maria Ilieva avatar
    4017 posts

    Posted 19 Nov 2015 Link to this post

    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
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Maria Ilieva
    Admin
    Maria Ilieva avatar
    4017 posts

    Posted 19 Nov 2015 Link to this post

    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
  5. Leoni
    Leoni avatar
    9 posts
    Member since:
    Jul 2012

    Posted 19 Nov 2015 in reply to Maria Ilieva Link to this post

    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.

     

     

  6. Answer
    Maria Ilieva
    Admin
    Maria Ilieva avatar
    4017 posts

    Posted 24 Nov 2015 Link to this post

    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
  7. Leoni
    Leoni avatar
    9 posts
    Member since:
    Jul 2012

    Posted 25 Nov 2015 in reply to Maria Ilieva Link to this post

    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'); }
            })
        }

  8. Leoni
    Leoni avatar
    9 posts
    Member since:
    Jul 2012

    Posted 27 Nov 2015 in reply to Leoni Link to this post

    Additional information :
  9. Dimo
    Admin
    Dimo avatar
    8331 posts

    Posted 27 Nov 2015 Link to this post

    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
  10. Mike
    Mike avatar
    1 posts
    Member since:
    Jul 2016

    Posted 11 Aug in reply to Maria Ilieva Link to this post

    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

  11. Dimo
    Admin
    Dimo avatar
    8331 posts

    Posted 15 Aug Link to this post

    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
Back to Top
UI for ASP.NET MVC is VS 2017 Ready